// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2017 The Decred developers
// Copyright (c) 2018-2020 The Hc developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/elliptic"
	"crypto/sha256"
	"crypto/subtle"
	"crypto/tls"
	"encoding/base64"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"math/big"
	"math/rand"
	"net"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/btcsuite/websocket"

	"github.com/HcashOrg/bitset"
	"github.com/HcashOrg/hcd/blockchain"
	"github.com/HcashOrg/hcd/blockchain/stake"
	"github.com/HcashOrg/hcd/chaincfg"
	"github.com/HcashOrg/hcd/chaincfg/chainec"
	"github.com/HcashOrg/hcd/chaincfg/chainhash"
	"github.com/HcashOrg/hcd/crypto/bliss"
	"github.com/HcashOrg/hcd/database"
	"github.com/HcashOrg/hcd/hcjson"
	"github.com/HcashOrg/hcd/hcutil"
	"github.com/HcashOrg/hcd/mempool"
	"github.com/HcashOrg/hcd/mining"
	"github.com/HcashOrg/hcd/txscript"
	"github.com/HcashOrg/hcd/wire"
)

// API version constants
const (
	jsonrpcSemverString = "3.1.0"
	jsonrpcSemverMajor  = 3
	jsonrpcSemverMinor  = 1
	jsonrpcSemverPatch  = 0
)

const (
	// rpcAuthTimeoutSeconds is the number of seconds a connection to the
	// RPC server is allowed to stay open without authenticating before it
	// is closed.
	rpcAuthTimeoutSeconds = 10

	// uint256Size is the number of bytes needed to represent an unsigned
	// 256-bit integer.
	uint256Size = 32

	// getworkDataLen is the length of the data field of the getwork RPC.
	// It consists of the serialized block header plus the internal blake256
	// padding.  The internal blake256 padding consists of a single 1 bit
	// followed by zeros and a final 1 bit in order to pad the message out
	// to 56 bytes followed by length of the message in bits encoded as a
	// big-endian uint64 (8 bytes).  Thus, the resulting length is a
	// multiple of the blake256 block size (64 bytes).  Given the padding
	// requires at least a 1 bit and 64 bits for the padding, the following
	// converts the block header length and hash block size to bits in order
	// to ensure the correct number of hash blocks are calculated and then
	// multiplies the result by the block hash block size in bytes.
	getworkDataLen = (1 + ((wire.MaxBlockHeaderPayload*8 + 65) /
		(chainhash.HashBlockSize * 8))) * chainhash.HashBlockSize

	// getworkExpirationDiff is the number of blocks below the current
	// best block in height to begin pruning out old block work from
	// the template pool.
	getworkExpirationDiff = 3

	// gbtNonceRange is two 32-bit big-endian hexadecimal integers which
	// represent the valid ranges of nonces returned by the getblocktemplate
	// RPC.
	gbtNonceRange = "00000000ffffffff"

	// gbtRegenerateSeconds is the number of seconds that must pass before
	// a new template is generated when the previous block hash has not
	// changed and there have been changes to the available transactions
	// in the memory pool.
	gbtRegenerateSeconds = 60

	// merkleRootPairSize
	merkleRootPairSize = 64

	// sstxCommitmentString is the string to insert when a verbose
	// transaction output's pkscript type is a ticket commitment.
	sstxCommitmentString = "sstxcommitment"

	// maxSigOpsPerTx is the maximum number of signature operations
	// in a single transaction we will relay or mine.  It is a fraction
	// of the max signature operations for a block.
	//
	// NOTE: This is being added while syncing upstream because the code in
	// the RPC server here is referencing the variable even though it most
	// definitely shouldn't be.  It is a policy limit regarding what should
	// be relayed or mined and thus should only apply in the mempool and/or
	// possibly the mining code.
	maxSigOpsPerTx = blockchain.MaxSigOpsPerBlock / 5
)

var (
	// blake256Pad is the extra blake256 internal padding needed for the
	// data of the getwork RPC.  It is set in the init routine since it is
	// based on the size of the block header and requires a bit of
	// calculation.
	blake256Pad []byte

	// gbtMutableFields are the manipulations the server allows to be made
	// to block templates generated by the getblocktemplate RPC.  It is
	// declared here to avoid the overhead of creating the slice on every
	// invocation for constant data.
	gbtMutableFields = []string{
		"time", "transactions/add", "prevblock", "coinbase/append",
	}

	// gbtCoinbaseAux describes additional data that miners should include
	// in the coinbase signature script.  It is declared here to avoid the
	// overhead of creating a new object on every invocation for constant
	// data.
	gbtCoinbaseAux = &hcjson.GetBlockTemplateResultAux{
		Flags: hex.EncodeToString(builderScript(txscript.
			NewScriptBuilder().AddData([]byte(coinbaseFlags)))),
	}

	// gbtCapabilities describes additional capabilities returned with a
	// block template generated by the getblocktemplate RPC.    It is
	// declared here to avoid the overhead of creating the slice on every
	// invocation for constant data.
	gbtCapabilities = []string{"proposal"}
)

// Errors
var (
	// ErrRPCUnimplemented is an error returned to RPC clients when the
	// provided command is recognized, but not implemented.
	ErrRPCUnimplemented = &hcjson.RPCError{
		Code:    hcjson.ErrRPCUnimplemented,
		Message: "Command unimplemented",
	}

	// ErrRPCNoWallet is an error returned to RPC clients when the provided
	// command is recognized as a wallet command.
	ErrRPCNoWallet = &hcjson.RPCError{
		Code:    hcjson.ErrRPCNoWallet,
		Message: "This implementation does not implement wallet commands",
	}

	// ErrInvalidLongPoll is an internal error code to indicate that
	// longpollid is not formated properly.
	ErrInvalidLongPoll = errors.New("invalid longpollid format")
)

type commandHandler func(*rpcServer, interface{}, <-chan struct{}) (interface{}, error)

// rpcHandlers maps RPC command strings to appropriate handler functions.
// This is set by init because help references rpcHandlers and thus causes
// a dependency loop.
var rpcHandlers map[string]commandHandler
var rpcHandlersBeforeInit = map[string]commandHandler{
	"addnode":               handleAddNode,
	"createrawsstx":         handleCreateRawSStx,
	"createrawssgentx":      handleCreateRawSSGenTx,
	"createrawssrtx":        handleCreateRawSSRtx,
	"createrawtransaction":  handleCreateRawTransaction,
	"debuglevel":            handleDebugLevel,
	"decoderawtransaction":  handleDecodeRawTransaction,
	"decodescript":          handleDecodeScript,
	"estimatefee":           handleEstimateFee,
	"estimatestakediff":     handleEstimateStakeDiff,
	"existsaddress":         handleExistsAddress,
	"existsaddresses":       handleExistsAddresses,
	"existsmissedtickets":   handleExistsMissedTickets,
	"existsexpiredtickets":  handleExistsExpiredTickets,
	"existsliveticket":      handleExistsLiveTicket,
	"existslivetickets":     handleExistsLiveTickets,
	"existsmempooltxs":      handleExistsMempoolTxs,
	"generate":              handleGenerate,
	"getaddednodeinfo":      handleGetAddedNodeInfo,
	"getbestblock":          handleGetBestBlock,
	"getbestblockhash":      handleGetBestBlockHash,
	"getblock":              handleGetBlock,
	"getblockcount":         handleGetBlockCount,
	"getblockhash":          handleGetBlockHash,
	"getblockheader":        handleGetBlockHeader,
	"getblocksubsidy":       handleGetBlockSubsidy,
	"getcoinsupply":         handleGetCoinSupply,
	"getconnectioncount":    handleGetConnectionCount,
	"getcurrentnet":         handleGetCurrentNet,
	"getdifficulty":         handleGetDifficulty,
	"getgenerate":           handleGetGenerate,
	"gethashespersec":       handleGetHashesPerSec,
	"getheaders":            handleGetHeaders,
	"getinfo":               handleGetInfo,
	"getblockchaininfo":     handleGetBlockchainInfo,
	"getmempoolinfo":        handleGetMempoolInfo,
	"getmininginfo":         handleGetMiningInfo,
	"getnettotals":          handleGetNetTotals,
	"getnetworkhashps":      handleGetNetworkHashPS,
	"getpeerinfo":           handleGetPeerInfo,
	"getrawmempool":         handleGetRawMempool,
	"getrawtransaction":     handleGetRawTransaction,
	"getstakedifficulty":    handleGetStakeDifficulty,
	"getstakeversioninfo":   handleGetStakeVersionInfo,
	"getstakeversions":      handleGetStakeVersions,
	"getticketpoolvalue":    handleGetTicketPoolValue,
	"getvoteinfo":           handleGetVoteInfo,
	"gettxout":              handleGetTxOut,
	"getwork":               handleGetWork,
	"help":                  handleHelp,
	"livetickets":           handleLiveTickets,
	"missedtickets":         handleMissedTickets,
	"node":                  handleNode,
	"ping":                  handlePing,
	"searchrawtransactions": handleSearchRawTransactions,
	"rebroadcastmissed":     handleRebroadcastMissed,
	"rebroadcastwinners":    handleRebroadcastWinners,
	"sendrawtransaction":    handleSendRawTransaction,
	"setgenerate":           handleSetGenerate,
	"stop":                  handleStop,
	"submitblock":           handleSubmitBlock,
	"ticketfeeinfo":         handleTicketFeeInfo,
	"ticketsforaddress":     handleTicketsForAddress,
	"ticketvwap":            handleTicketVWAP,
	"txfeeinfo":             handleTxFeeInfo,
	"validateaddress":       handleValidateAddress,
	"verifychain":           handleVerifyChain,
	"verifymessage":         handleVerifyMessage,
	"verifyblissmessage":    handleVerifyBlissMessage,
	"version":               handleVersion,
}

// list of commands that we recognize, but for which hcd has no support because
// it lacks support for wallet functionality. For these commands the user
// should ask a connected instance of hcwallet.
var rpcAskWallet = map[string]struct{}{
	"accountaddressindex":     {},
	"accountsyncaddressindex": {},
	"addmultisigaddress":      {},
	"addticket":               {},
	"createencryptedwallet":   {},
	"createmultisig":          {},
	"dumpprivkey":             {},
	"getaccount":              {},
	"getaccountaddress":       {},
	"getaddressesbyaccount":   {},
	"getbalance":              {},
	"getnewaddress":           {},
	"getrawchangeaddress":     {},
	"getreceivedbyaccount":    {},
	"getreceivedbyaddress":    {},
	"getstakeinfo":            {},
	"getvotechoices":          {},
	"gettransaction":          {},
	"gettxoutsetinfo":         {},
	"getunconfirmedbalance":   {},
	"importprivkey":           {},
	"keypoolrefill":           {},
	"listaccounts":            {},
	"listlockunspent":         {},
	"listreceivedbyaccount":   {},
	"listreceivedbyaddress":   {},
	"listsinceblock":          {},
	"listtransactions":        {},
	"listunspent":             {},
	"lockunspent":             {},
	"rescanwallet":            {},
	"revoketickets":           {},
	"sendfrom":                {},
	"sendmany":                {},
	"sendtoaddress":           {},
	"setvotechoice":           {},
	"settxfee":                {},
	"signmessage":             {},
	"signrawtransaction":      {},
	"stakepooluserinfo":       {},
	"walletinfo":              {},
	"walletlock":              {},
	"walletpassphrase":        {},
	"walletpassphrasechange":  {},
}

// Commands that are currently unimplemented, but should ultimately be.
var rpcUnimplemented = map[string]struct{}{
	"estimatefee":       {},
	"estimatepriority":  {},
	"getblocktemplate":  {},
	"getblockchaininfo": {},
	"getchaintips":      {},
	"getnetworkinfo":    {},
}

// Commands that are available to a limited user
var rpcLimited = map[string]struct{}{
	// Websockets commands
	"notifyblocks":          {},
	"notifynewtransactions": {},
	"notifyreceived":        {},
	"notifyspent":           {},
	"rescan":                {},
	"session":               {},

	// Websockets AND HTTP/S commands
	"help": {},

	// HTTP/S-only commands
	"createrawtransaction":  {},
	"decoderawtransaction":  {},
	"decodescript":          {},
	"getbestblock":          {},
	"getbestblockhash":      {},
	"getblock":              {},
	"getblockcount":         {},
	"getblockhash":          {},
	"getcurrentnet":         {},
	"getdifficulty":         {},
	"getinfo":               {},
	"getnettotals":          {},
	"getnetworkhashps":      {},
	"getrawmempool":         {},
	"getrawtransaction":     {},
	"gettxout":              {},
	"searchrawtransactions": {},
	"sendrawtransaction":    {},
	"submitblock":           {},
	"validateaddress":       {},
	"verifymessage":         {},
	"verifyblissmessage":    {},
	"version":               {},
}

// builderScript is a convenience function which is used for hard-coded scripts
// built with the script builder.   Any errors are converted to a panic since it
// is only, and must only, be used with hard-coded, and therefore, known good,
// scripts.
func builderScript(builder *txscript.ScriptBuilder) []byte {
	script, err := builder.Script()
	if err != nil {
		panic(err)
	}
	return script
}

// rpcInternalError is a convenience function to convert an internal error to
// an RPC error with the appropriate code set.  It also logs the error to the
// RPC server subsystem since internal errors really should not occur.  The
// context parameter is only used in the log message and may be empty if it's
// not needed.
func rpcInternalError(errStr, context string) *hcjson.RPCError {
	logStr := errStr
	if context != "" {
		logStr = context + ": " + errStr
	}
	rpcsLog.Error(logStr)
	return hcjson.NewRPCError(hcjson.ErrRPCInternal.Code, errStr)
}

// rpcInvalidError is a convenience function to convert an invalid parameter
// error to an RPC error with the appropriate code set.
func rpcInvalidError(fmtStr string, args ...interface{}) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCInvalidParameter,
		fmt.Sprintf(fmtStr, args...))
}

// rpcDeserializetionError is a convenience function to convert a
// deserialization error to an RPC error with the appropriate code set.
func rpcDeserializationError(fmtStr string, args ...interface{}) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCDeserialization,
		fmt.Sprintf(fmtStr, args...))
}

// rpcRuleError is a convenience function to convert a
// rule error to an RPC error with the appropriate code set.
func rpcRuleError(fmtStr string, args ...interface{}) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCMisc,
		fmt.Sprintf(fmtStr, args...))
}

// rpcAddressKeyError is a convenience function to convert an address/key error to
// an RPC error with the appropriate code set.  It also logs the error to the
// RPC server subsystem since internal errors really should not occur.  The
// context parameter is only used in the log message and may be empty if it's
// not needed.
func rpcAddressKeyError(fmtStr string, args ...interface{}) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCInvalidAddressOrKey,
		fmt.Sprintf(fmtStr, args...))
}

// rpcDecodeHexError is a convenience function for returning a nicely formatted
// RPC error which indicates the provided hex string failed to decode.
func rpcDecodeHexError(gotHex string) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCDecodeHexString,
		fmt.Sprintf("Argument must be hexadecimal string (not %q)",
			gotHex))
}

// rpcNoTxInfoError is a convenience function for returning a nicely formatted
// RPC error which indicates there is no information available for the provided
// transaction hash.
func rpcNoTxInfoError(txHash *chainhash.Hash) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCNoTxInfo,
		fmt.Sprintf("No information available about transaction %v",
			txHash))
}

// rpcMiscError is a convenience function for returning a nicely formatted RPC
// error which indicates there is a unquantifiable error.  Use this sparingly;
// misc return codes are a cop out.
func rpcMiscError(message string) *hcjson.RPCError {
	return hcjson.NewRPCError(hcjson.ErrRPCMisc, message)
}

// workStateBlockInfo houses information about how to reconstruct a block given
// its template and signature script.
type workStateBlockInfo struct {
	msgBlock *wire.MsgBlock
	pkScript []byte
}

// workState houses state that is used in between multiple RPC invocations to
// getwork.
type workState struct {
	sync.Mutex
	lastTxUpdate  time.Time
	lastGenerated time.Time
	prevHash      *chainhash.Hash
	msgBlock      *wire.MsgBlock
	extraNonce    uint64
}

// newWorkState returns a new instance of a workState with all internal fields
// initialized and ready to use.
func newWorkState() *workState {
	return &workState{}
}

// gbtWorkState houses state that is used in between multiple RPC invocations to
// getblocktemplate.
type gbtWorkState struct {
	sync.Mutex
	lastTxUpdate  time.Time
	lastGenerated time.Time
	prevHash      *chainhash.Hash
	minTimestamp  time.Time
	template      *BlockTemplate
	notifyMap     map[chainhash.Hash]map[int64]chan struct{}
	timeSource    blockchain.MedianTimeSource
}

// newGbtWorkState returns a new instance of a gbtWorkState with all internal
// fields initialized and ready to use.
func newGbtWorkState(timeSource blockchain.MedianTimeSource) *gbtWorkState {
	return &gbtWorkState{
		notifyMap:  make(map[chainhash.Hash]map[int64]chan struct{}),
		timeSource: timeSource,
	}
}

// handleUnimplemented is the handler for commands that should ultimately be
// supported but are not yet implemented.
func handleUnimplemented(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return nil, ErrRPCUnimplemented
}

// handleAskWallet is the handler for commands that are recognized as valid, but
// are unable to answer correctly since it involves wallet state.
// These commands will be implemented in hcwallet.
func handleAskWallet(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return nil, ErrRPCNoWallet
}

// handleAddNode handles addnode commands.
func handleAddNode(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.AddNodeCmd)

	addr := normalizeAddress(c.Addr, activeNetParams.DefaultPort)
	var err error
	switch c.SubCmd {
	case "add":
		err = s.server.ConnectNode(addr, true)
	case "remove":
		err = s.server.RemoveNodeByAddr(addr)
	case "onetry":
		err = s.server.ConnectNode(addr, false)
	default:
		return nil, rpcInvalidError("Invalid subcommand for addnode")
	}

	if err != nil {
		return nil, rpcInvalidError("%v: %v", c.SubCmd, err)
	}

	// no data returned unless an error.
	return nil, nil
}

// handleNode handles node commands.
func handleNode(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.NodeCmd)

	var addr string
	var nodeID uint64
	var errN, err error
	switch c.SubCmd {
	case "disconnect":
		// If we have a valid uint disconnect by node id. Otherwise,
		// attempt to disconnect by address, returning an error if a
		// valid IP address is not supplied.
		if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil {
			err = s.server.DisconnectNodeByID(int32(nodeID))
		} else {
			if _, _, errP := net.SplitHostPort(c.Target); errP == nil ||
				net.ParseIP(c.Target) != nil {
				addr = normalizeAddress(c.Target, activeNetParams.DefaultPort)
				err = s.server.DisconnectNodeByAddr(addr)
			} else {
				return nil, rpcInvalidError("%v: Invalid "+
					"address or node ID", c.SubCmd)
			}
		}
		if err != nil &&
			peerExists(s.server.Peers(), addr, int32(nodeID)) {
			return nil, rpcMiscError("Can't disconnect a " +
				"permanent peer, use remove")
		}
	case "remove":
		// If we have a valid uint disconnect by node id. Otherwise,
		// attempt to disconnect by address, returning an error if a
		// valid IP address is not supplied.
		if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil {
			err = s.server.RemoveNodeByID(int32(nodeID))
		} else {
			if _, _, errP := net.SplitHostPort(c.Target); errP == nil ||
				net.ParseIP(c.Target) != nil {
				addr = normalizeAddress(c.Target, activeNetParams.DefaultPort)
				err = s.server.RemoveNodeByAddr(addr)
			} else {
				return nil, rpcInvalidError("%v: invalid "+
					"address or node ID", c.SubCmd)
			}
		}
		if err != nil &&
			peerExists(s.server.Peers(), addr, int32(nodeID)) {
			return nil, rpcMiscError("can't remove a temporary " +
				"peer, use disconnect")
		}
	case "connect":
		addr = normalizeAddress(c.Target, activeNetParams.DefaultPort)

		// Default to temporary connections.
		subCmd := "temp"
		if c.ConnectSubCmd != nil {
			subCmd = *c.ConnectSubCmd
		}

		switch subCmd {
		case "perm", "temp":
			err = s.server.ConnectNode(addr, subCmd == "perm")
		default:
			return nil, rpcInvalidError("%v: invalid subcommand "+
				"for node connect", subCmd)
		}
	default:
		return nil, rpcInvalidError("%v: invalid subcommand for node",
			c.SubCmd)
	}

	if err != nil {
		return nil, rpcInvalidError("%v: %v", c.SubCmd, err)
	}

	// no data returned unless an error.
	return nil, nil
}

// peerExists determines if a certain peer is currently connected given
// information about all currently connected peers. Peer existence is
// determined using either a target address or node id.
func peerExists(peers []*serverPeer, addr string, nodeID int32) bool {
	for _, p := range peers {
		if p.ID() == nodeID || p.Addr() == addr {
			return true
		}
	}
	return false
}

// messageToHex serializes a message to the wire protocol encoding using the
// latest protocol version and returns a hex-encoded string of the result.
func messageToHex(msg wire.Message) (string, error) {
	var buf bytes.Buffer
	if err := msg.BtcEncode(&buf, maxProtocolVersion); err != nil {
		context := fmt.Sprintf("Failed to encode msg of type %T", msg)
		return "", rpcInternalError(err.Error(), context)
	}

	return hex.EncodeToString(buf.Bytes()), nil
}

// handleCreateRawTransaction handles createrawtransaction commands.
func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.CreateRawTransactionCmd)

	// Validate the locktime, if given.
	if c.LockTime != nil &&
		(*c.LockTime < 0 ||
			*c.LockTime > int64(wire.MaxTxInSequenceNum)) {
		return nil, rpcInvalidError("Locktime out of range")
	}

	// Add all transaction inputs to a new transaction after performing
	// some validity checks.
	mtx := wire.NewMsgTx()
	for _, input := range c.Inputs {
		txHash, err := chainhash.NewHashFromStr(input.Txid)
		if err != nil {
			return nil, rpcDecodeHexError(input.Txid)
		}

		if !(input.Tree == wire.TxTreeRegular ||
			input.Tree == wire.TxTreeStake) {
			return nil, rpcInvalidError("Tx tree must be regular " +
				"or stake")
		}

		prevOut := wire.NewOutPoint(txHash, input.Vout, input.Tree)
		txIn := wire.NewTxIn(prevOut, []byte{})
		if c.LockTime != nil && *c.LockTime != 0 {
			txIn.Sequence = wire.MaxTxInSequenceNum - 1
		}
		mtx.AddTxIn(txIn)
	}

	// Add all transaction outputs to the transaction after performing
	// some validity checks.
	for encodedAddr, amount := range c.Amounts {
		// Ensure amount is in the valid range for monetary amounts.
		if amount <= 0 || amount > hcutil.MaxAmount {
			return nil, rpcInvalidError("Invalid amount: 0 >= %v "+
				"> %v", amount, hcutil.MaxAmount)
		}

		// Decode the provided address.
		addr, err := hcutil.DecodeAddress(encodedAddr)
		if err != nil {
			return nil, rpcAddressKeyError("Could not decode "+
				"address: %v", err)
		}

		// Ensure the address is one of the supported types and that
		// the network encoded with the address matches the network the
		// server is currently on.
		switch addr.(type) {
		case *hcutil.AddressPubKeyHash:
		case *hcutil.AddressScriptHash:
		default:
			return nil, rpcAddressKeyError("Invalid type: %T", addr)
		}
		if !addr.IsForNet(s.server.chainParams) {
			return nil, rpcAddressKeyError("Wrong network: %v",
				addr)
		}

		// Create a new script which pays to the provided address.
		pkScript, err := txscript.PayToAddrScript(addr)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Pay to adress script")
		}

		atomic, err := hcutil.NewAmount(amount)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"New amount")
		}

		txOut := wire.NewTxOut(int64(atomic), pkScript)
		mtx.AddTxOut(txOut)
	}

	// Set the Locktime, if given.
	if c.LockTime != nil {
		mtx.LockTime = uint32(*c.LockTime)
	}

	if c.PayLoad != nil && (*c.PayLoad) != "" {
		payLoad, _ := hex.DecodeString(*c.PayLoad)
		payLoadScript, err := txscript.GenerateProvablyPruneableOut(payLoad)
		if err == nil {
			payLoadTx := &wire.TxOut{
				Value:    int64(0),
				PkScript: payLoadScript,
			}
			mtx.AddTxOut(payLoadTx)
			//unsignedTransaction.TxOut = append(unsignedTransaction.TxOut, payLoadTx)
		}
	}

	// Return the serialized and hex-encoded transaction.  Note that this
	// is intentionally not directly returning because the first return
	// value is a string and it would result in returning an empty string to
	// the client instead of nothing (nil) in the case of an error.
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}
	return mtxHex, nil
}

// handleCreateRawSStx handles createrawsstx commands.
func handleCreateRawSStx(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.CreateRawSStxCmd)

	// Basic sanity checks for the information coming from the cmd.
	if len(c.Inputs) != len(c.COuts) {
		return nil, rpcInvalidError("Number of inputs should be equal "+
			"to the number of future commitment/change outs for "+
			"any sstx; %v inputs given, but %v COuts",
			len(c.Inputs), len(c.COuts))
	}
	if len(c.Amount) != 1 {
		return nil, rpcInvalidError("Only one SSGen tagged output is "+
			"allowed per sstx; len ssgenout %v", len(c.Amount))
	}

	// Add all transaction inputs to a new transaction after performing
	// some validity checks.
	mtx := wire.NewMsgTx()
	for _, input := range c.Inputs {
		txHash, err := chainhash.NewHashFromStr(input.Txid)
		if err != nil {
			return nil, rpcDecodeHexError(input.Txid)
		}

		if input.Vout < 0 {
			return nil, rpcInvalidError("Vout must be positive")
		}

		if !(input.Tree == wire.TxTreeRegular ||
			input.Tree == wire.TxTreeStake) {
			rpcInvalidError("Tx tree must be regular or stake")
		}

		prevOut := wire.NewOutPoint(txHash, input.Vout, input.Tree)
		txIn := wire.NewTxIn(prevOut, []byte{})
		mtx.AddTxIn(txIn)
	}

	// Add all transaction outputs to the transaction after performing
	// some validity checks.
	amtTicket := int64(0)

	for encodedAddr, amount := range c.Amount {
		// Ensure amount is in the valid range for monetary amounts.
		if amount <= 0 || amount > hcutil.MaxAmount {
			return nil, rpcInvalidError("Invalid SSTx commitment "+
				"amount: 0 >= %v > %v", amount,
				hcutil.MaxAmount)
		}

		// Decode the provided address.
		addr, err := hcutil.DecodeAddress(encodedAddr)
		if err != nil {
			return nil, rpcAddressKeyError("Could not decode "+
				"address: %v", err)
		}

		// Ensure the address is one of the supported types and that
		// the network encoded with the address matches the network the
		// server is currently on.
		switch addr.(type) {
		case *hcutil.AddressPubKeyHash:
		case *hcutil.AddressScriptHash:
		default:
			return nil, rpcAddressKeyError("Invalid address type: "+
				"%T", addr)
		}
		if !addr.IsForNet(s.server.chainParams) {
			return nil, rpcAddressKeyError("Wrong network: %v",
				addr)
		}

		// Create a new script which pays to the provided address with an
		// SStx tagged output.
		pkScript, err := txscript.PayToSStx(addr)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not create TX script")
		}

		txOut := wire.NewTxOut(amount, pkScript)
		mtx.AddTxOut(txOut)

		amtTicket += amount
	}

	// Calculated the commitment amounts, then create the
	// addresses and payout proportions as null data
	// outputs.
	inputAmts := make([]int64, len(c.Inputs))
	for i, input := range c.Inputs {
		inputAmts[i] = input.Amt
	}
	changeAmts := make([]int64, len(c.COuts))
	for i, cout := range c.COuts {
		changeAmts[i] = cout.ChangeAmt
	}

	// Check and make sure none of the change overflows
	// the input amounts.
	for i, amt := range inputAmts {
		if changeAmts[i] >= amt {
			return nil, rpcInvalidError("input %v >= amount %v",
				changeAmts[i], amt)
		}
	}

	// Obtain the commitment amounts.
	_, amountsCommitted, err := stake.SStxNullOutputAmounts(inputAmts,
		changeAmts, amtTicket)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Invalid SSTx output amounts")
	}

	for i, cout := range c.COuts {
		// 1. Append future commitment output.
		addr, err := hcutil.DecodeAddress(cout.Addr)
		if err != nil {
			return nil, rpcAddressKeyError("Could not decode "+
				"address: %v", err)
		}

		// Ensure the address is one of the supported types and that
		// the network encoded with the address matches the network the
		// server is currently on.
		switch addr.(type) {
		case *hcutil.AddressPubKeyHash:
			break
		case *hcutil.AddressScriptHash:
			break
		default:
			return nil, rpcAddressKeyError("Invalid type: %T", addr)
		}
		if !addr.IsForNet(s.server.chainParams) {
			return nil, rpcAddressKeyError("Wrong network: %v",
				addr)
		}

		// Create an OP_RETURN push containing the pubkeyhash to send
		// rewards to.  TODO Replace 0x0000 fee limits with an argument
		// passed to the RPC call.
		pkScript, err := txscript.GenerateSStxAddrPush(addr,
			hcutil.Amount(amountsCommitted[i]), 0x0000)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not create SStx script")
		}
		txout := wire.NewTxOut(int64(0), pkScript)
		mtx.AddTxOut(txout)

		// 2. Append change output.

		// Ensure amount is in the valid range for monetary amounts.
		if cout.ChangeAmt < 0 || cout.ChangeAmt > hcutil.MaxAmount {
			return nil, rpcInvalidError("Invalid change amount: 0 "+
				"> %v > %v", cout.ChangeAmt, hcutil.MaxAmount)
		}

		// Decode the provided address.
		addr, err = hcutil.DecodeAddress(cout.ChangeAddr)
		if err != nil {
			return nil, rpcAddressKeyError("Wrong network: %v",
				addr)
		}

		// Ensure the address is one of the supported types and that
		// the network encoded with the address matches the network the
		// server is currently on.
		switch addr.(type) {
		case *hcutil.AddressPubKeyHash:
			break
		case *hcutil.AddressScriptHash:
			break
		default:
			return nil, rpcAddressKeyError("Invalid type: %T", addr)
		}
		if !addr.IsForNet(s.server.chainParams) {
			return nil, rpcAddressKeyError("Wrong network: %v",
				addr)
		}

		// Create a new script which pays to the provided address with
		// an SStx change tagged output.
		pkScript, err = txscript.PayToSStxChange(addr)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not create SStx change script")
		}

		txOut := wire.NewTxOut(cout.ChangeAmt, pkScript)
		mtx.AddTxOut(txOut)
	}

	// Make sure we generated a valid SStx.
	if _, err := stake.IsSStx(mtx); err != nil {
		return nil, rpcInternalError(err.Error(),
			"Invalid SStx")
	}

	// Return the serialized and hex-encoded transaction.
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}
	return mtxHex, nil
}

// handleCreateRawSSGenTx handles createrawssgentx commands.
func handleCreateRawSSGenTx(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.CreateRawSSGenTxCmd)
	// Only a single SStx should be given
	if len(c.Inputs) != 1 {
		return nil, rpcInvalidError("SSGen Tx can only have one valid input")
	}

	// 1. Fetch the SStx, then calculate all the values we'll need later for
	// the generation of the SSGen tx outputs.
	//
	// Convert the provided transaction hash hex to a chainhash.Hash.
	txHash, err := chainhash.NewHashFromStr(c.Inputs[0].Txid)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCBlockNotFound,
			Message: fmt.Sprintf("Inputs 0 Txid: %v", err),
		}
	}

	// Try to fetch the ticket from the block database.
	ticketUtx, err := s.chain.FetchUtxoEntry(txHash)
	if ticketUtx == nil || err != nil {
		return nil, rpcNoTxInfoError(txHash)
	}
	if t := ticketUtx.TransactionType(); t != stake.TxTypeSStx {
		return nil, rpcDeserializationError("Invalid Tx type: %v", t)
	}

	// Store the sstx pubkeyhashes and amounts as found in the transaction
	// outputs.
	minimalOutputs := blockchain.ConvertUtxosToMinimalOutputs(ticketUtx)
	ssgenPayTypes, ssgenPkhs, sstxAmts, _, _, _, sigTypes :=
		stake.SStxStakeOutputInfo(minimalOutputs)

	// Get the current reward.
	blockHash, curHeight := s.server.blockManager.chainState.Best()
	stakeVoteSubsidy := blockchain.CalcStakeVoteSubsidy(
		s.chain.FetchSubsidyCache(), curHeight, activeNetParams.Params)

	// Calculate the output values from this data.
	ssgenCalcAmts := stake.CalculateRewards(sstxAmts,
		minimalOutputs[0].Value,
		stakeVoteSubsidy)

	// 2. Add all transaction inputs to a new transaction after performing
	// some validity checks. First, add the stake base, then the OP_SSTX
	// tagged output.
	mtx := wire.NewMsgTx()

	stakeBaseOutPoint := wire.NewOutPoint(&chainhash.Hash{},
		uint32(0xFFFFFFFF), int8(0x00))
	txInStakeBase := wire.NewTxIn(stakeBaseOutPoint, []byte{})
	mtx.AddTxIn(txInStakeBase)

	for _, input := range c.Inputs {
		txHash, err := chainhash.NewHashFromStr(input.Txid)
		if err != nil {
			return nil, rpcDecodeHexError(input.Txid)
		}

		if input.Vout < 0 {
			return nil, rpcInvalidError("Vout must be positive")
		}

		if !(input.Tree == wire.TxTreeStake) {
			return nil, rpcInvalidError("Input tree is not " +
				"TxTreeStake type")
		}

		prevOut := wire.NewOutPoint(txHash, input.Vout, input.Tree)
		txIn := wire.NewTxIn(prevOut, []byte{})
		mtx.AddTxIn(txIn)
	}

	// 3. Add the OP_RETURN null data pushes of the block header hash, the
	// block height, and votebits, then add all the OP_SSGEN tagged
	// outputs.
	//
	// Block reference output.
	blockRefScript, err := txscript.GenerateSSGenBlockRef(*blockHash,
		uint32(curHeight))
	if err != nil {
		return nil, rpcInvalidError("Could not generate SSGen block "+
			"reference: %v", err)
	}
	blockRefOut := wire.NewTxOut(0, blockRefScript)
	mtx.AddTxOut(blockRefOut)

	// Votebits output.
	blockVBScript, err := txscript.GenerateSSGenVotes(c.VoteBits)
	if err != nil {
		return nil, rpcInvalidError("Could not generate SSGen votes: "+
			"%v", err)
	}
	blockVBOut := wire.NewTxOut(0, blockVBScript)
	mtx.AddTxOut(blockVBOut)
	// Add all the SSGen-tagged transaction outputs to the transaction
	// after performing some validity checks.
	for i, ssgenPkh := range ssgenPkhs {
		// Ensure amount is in the valid range for monetary amounts.
		if ssgenCalcAmts[i] <= 0 ||
			ssgenCalcAmts[i] > hcutil.MaxAmount {
			return nil, rpcInvalidError("Invalid SSGen amounts: "+
				"0 >= %v > %v", ssgenCalcAmts[i],
				hcutil.MaxAmount)
		}

		// Create a new script which pays to the provided address
		// specified in the original ticket tx.
		var ssgenOut []byte
		switch ssgenPayTypes[i] {
		case false: // P2PKH
			ssgenOut, err = txscript.PayToSSGenPKHDirect(ssgenPkh, int(sigTypes[i]))
			if err != nil {
				return nil,
					rpcInvalidError("Could not generate "+
						"PKH script: %v", err)
			}
		case true: // P2SH
			ssgenOut, err = txscript.PayToSSGenSHDirect(ssgenPkh, int(sigTypes[i]))
			if err != nil {
				return nil,
					rpcInvalidError("Could not generate "+
						"SHD script: %v", err)
			}
		}

		// Add the txout to our SSGen tx.
		txOut := wire.NewTxOut(ssgenCalcAmts[i], ssgenOut)
		mtx.AddTxOut(txOut)
	}

	// Check to make sure our SSGen was created correctly.
	_, err = stake.IsSSGen(mtx)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Invalid SSGen")
	}

	// Return the serialized and hex-encoded transaction.
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}
	return mtxHex, nil
}

// handleCreateRawSSRtx handles createrawssrtx commands.
func handleCreateRawSSRtx(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.CreateRawSSRtxCmd)

	// Only a single SStx should be given
	if len(c.Inputs) != 1 {
		return nil, rpcInvalidError("SSRtx invalid number of inputs")
	}

	// Decode the fee as coins.
	var feeAmt hcutil.Amount
	if c.Fee != nil {
		var err error
		feeAmt, err = hcutil.NewAmount(*c.Fee)
		if err != nil {
			return nil, rpcInvalidError("Invalid fee amount: %v",
				err)
		}
	}

	// 1. Fetch the SStx, then calculate all the values we'll need later
	// for the generation of the SSGen tx outputs.
	//
	// Convert the provided transaction hash hex to a chainhash.Hash.
	txHash, err := chainhash.NewHashFromStr(c.Inputs[0].Txid)
	if err != nil {
		return nil, rpcDecodeHexError(c.Inputs[0].Txid)
	}

	// Try to fetch the ticket from the block database.
	ticketUtx, err := s.chain.FetchUtxoEntry(txHash)
	if ticketUtx == nil || err != nil {
		return nil, rpcNoTxInfoError(txHash)
	}
	if t := ticketUtx.TransactionType(); t != stake.TxTypeSStx {
		return nil, rpcDeserializationError("Invalid Tx type: %v", t)
	}

	// Store the sstx pubkeyhashes and amounts as found in the transaction
	// outputs.
	minimalOutputs := blockchain.ConvertUtxosToMinimalOutputs(ticketUtx)
	ssrtxPayTypes, ssrtxPkhs, sstxAmts, _, _, _, sigTypes :=
		stake.SStxStakeOutputInfo(minimalOutputs)

	// 2. Add all transaction inputs to a new transaction after performing
	// some validity checks; the only input for an SSRtx is an OP_SSTX tagged
	// output.
	mtx := wire.NewMsgTx()
	for _, input := range c.Inputs {
		txHash, err := chainhash.NewHashFromStr(input.Txid)
		if err != nil {
			return nil, rpcDecodeHexError(input.Txid)
		}

		if input.Vout < 0 {
			return nil, rpcInvalidError("Vout must be positive")
		}

		if !(input.Tree == wire.TxTreeStake) {
			return nil, rpcInvalidError("Input tree is not " +
				"TxTreeStake type")
		}

		prevOut := wire.NewOutPoint(txHash, input.Vout, input.Tree)
		txIn := wire.NewTxIn(prevOut, []byte{})
		mtx.AddTxIn(txIn)
	}

	// 3. Add all the OP_SSRTX tagged outputs.

	// Calculate the output values from this data.
	ssrtxCalcAmts := stake.CalculateRewards(sstxAmts,
		minimalOutputs[0].Value, 0) // No subsidy for a revocation

	// Add all the SSRtx-tagged transaction outputs to the transaction after
	// performing some validity checks.
	feeApplied := false
	for i, ssrtxPkh := range ssrtxPkhs {
		// Ensure amount is in the valid range for monetary amounts.
		if sstxAmts[i] <= 0 || sstxAmts[i] > hcutil.MaxAmount {
			return nil, rpcInvalidError("Invalid SSTx amount: 0 >="+
				" %v > %v", sstxAmts[i] <= 0, hcutil.MaxAmount)
		}

		// Create a new script which pays to the provided address specified in
		// the original ticket tx.
		var ssrtxOutScript []byte
		switch ssrtxPayTypes[i] {
		case false: // P2PKH
			ssrtxOutScript, err = txscript.PayToSSRtxPKHDirect(ssrtxPkh, int(sigTypes[i]))
			if err != nil {
				return nil, rpcInvalidError("Could not "+
					"generate PKH script: %v", err)
			}
		case true: // P2SH
			ssrtxOutScript, err = txscript.PayToSSRtxSHDirect(ssrtxPkh, int(sigTypes[i]))
			if err != nil {
				return nil, rpcInvalidError("Could not "+
					"generate SHD script: %v", err)
			}
		}

		// Add the txout to our SSGen tx.
		amt := ssrtxCalcAmts[i]
		if !feeApplied && int64(feeAmt) < amt {
			amt -= int64(feeAmt)
			feeApplied = true
		}
		txOut := wire.NewTxOut(amt, ssrtxOutScript)
		mtx.AddTxOut(txOut)
	}

	// Check to make sure our SSRtx was created correctly.
	_, err = stake.IsSSRtx(mtx)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Invalid SSRtx")
	}

	// Return the serialized and hex-encoded transaction.
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}
	return mtxHex, nil
}

// handleDebugLevel handles debuglevel commands.
func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.DebugLevelCmd)

	// Special show command to list supported subsystems.
	if c.LevelSpec == "show" {
		return fmt.Sprintf("Supported subsystems %v",
			supportedSubsystems()), nil
	}

	err := parseAndSetDebugLevels(c.LevelSpec)
	if err != nil {
		return nil, rpcInvalidError("Invalid debug level %v: %v",
			c.LevelSpec, err)
	}

	return "Done.", nil
}

// createVinList returns a slice of JSON objects for the inputs of the passed
// transaction.
func createVinList(mtx *wire.MsgTx) []hcjson.Vin {
	// Coinbase transactions only have a single txin by definition.
	vinList := make([]hcjson.Vin, len(mtx.TxIn))
	if blockchain.IsCoinBaseTx(mtx) {
		txIn := mtx.TxIn[0]
		vinEntry := &vinList[0]
		vinEntry.Coinbase = hex.EncodeToString(txIn.SignatureScript)
		vinEntry.Sequence = txIn.Sequence
		vinEntry.AmountIn = hcutil.Amount(txIn.ValueIn).ToCoin()
		vinEntry.BlockHeight = txIn.BlockHeight
		vinEntry.BlockIndex = txIn.BlockIndex
		return vinList
	}

	for i, txIn := range mtx.TxIn {
		// The disassembled string will contain [error] inline
		// if the script doesn't fully parse, so ignore the
		// error here.
		disbuf, _ := txscript.DisasmString(txIn.SignatureScript)

		vinEntry := &vinList[i]
		vinEntry.Txid = txIn.PreviousOutPoint.Hash.String()
		vinEntry.Vout = txIn.PreviousOutPoint.Index
		vinEntry.Tree = txIn.PreviousOutPoint.Tree
		vinEntry.Sequence = txIn.Sequence
		vinEntry.Stakebase = hex.EncodeToString(txIn.SignatureScript)
		vinEntry.AmountIn = hcutil.Amount(txIn.ValueIn).ToCoin()
		vinEntry.BlockHeight = txIn.BlockHeight
		vinEntry.BlockIndex = txIn.BlockIndex
		vinEntry.ScriptSig = &hcjson.ScriptSig{
			Asm: disbuf,
			Hex: hex.EncodeToString(txIn.SignatureScript),
		}
	}

	return vinList
}

// createVoutList returns a slice of JSON objects for the outputs of the passed
// transaction.
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []hcjson.Vout {

	txType := stake.DetermineTxType(mtx)
	voutList := make([]hcjson.Vout, 0, len(mtx.TxOut))
	for i, v := range mtx.TxOut {
		// The disassembled string will contain [error] inline if the
		// script doesn't fully parse, so ignore the error here.
		disbuf, _ := txscript.DisasmString(v.PkScript)

		// Attempt to extract addresses from the public key script.  In
		// the case of stake submission transactions, the odd outputs
		// contain a commitment address, so detect that case
		// accordingly.
		var addrs []hcutil.Address
		var scriptClass string
		var reqSigs int
		var commitAmt *hcutil.Amount
		if txType == stake.TxTypeSStx && (i%2 != 0) {
			scriptClass = sstxCommitmentString
			addr, err := stake.AddrFromSStxPkScrCommitment(v.PkScript,
				chainParams)
			if err != nil {
				rpcsLog.Warnf("failed to decode ticket "+
					"commitment addr output for tx hash "+
					"%v, output idx %v", mtx.TxHash(), i)
			} else {
				addrs = []hcutil.Address{addr}
			}
			amt, err := stake.AmountFromSStxPkScrCommitment(v.PkScript)
			if err != nil {
				rpcsLog.Warnf("failed to decode ticket "+
					"commitment amt output for tx hash %v"+
					", output idx %v", mtx.TxHash(), i)
			} else {
				commitAmt = &amt
			}
		} else {
			// Ignore the error here since an error means the script
			// couldn't parse and there is no additional information
			// about it anyways.
			var sc txscript.ScriptClass
			sc, addrs, reqSigs, _ = txscript.ExtractPkScriptAddrs(
				v.Version, v.PkScript, chainParams)
			scriptClass = sc.String()
		}

		// Encode the addresses while checking if the address passes the
		// filter when needed.
		passesFilter := len(filterAddrMap) == 0
		encodedAddrs := make([]string, len(addrs))
		for j, addr := range addrs {
			encodedAddr := addr.EncodeAddress()
			encodedAddrs[j] = encodedAddr

			// No need to check the map again if the filter already
			// passes.
			if passesFilter {
				continue
			}
			if _, exists := filterAddrMap[encodedAddr]; exists {
				passesFilter = true
			}
		}

		if !passesFilter {
			continue
		}

		var vout hcjson.Vout
		voutSPK := &vout.ScriptPubKey
		vout.N = uint32(i)
		vout.Value = hcutil.Amount(v.Value).ToCoin()
		vout.Version = v.Version
		voutSPK.Addresses = encodedAddrs
		voutSPK.Asm = disbuf
		voutSPK.Hex = hex.EncodeToString(v.PkScript)
		voutSPK.Type = scriptClass
		voutSPK.ReqSigs = int32(reqSigs)
		if commitAmt != nil {
			voutSPK.CommitAmt = hcjson.Float64(commitAmt.ToCoin())
		}

		voutList = append(voutList, vout)
	}

	return voutList
}

// createTxRawResult converts the passed transaction and associated parameters
// to a raw transaction JSON object.
func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx, txHash string, blkIdx uint32, blkHeader *wire.BlockHeader, blkHash string, blkHeight int64, confirmations int64) (*hcjson.TxRawResult, error) {
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}

	if txHash != mtx.TxHash().String() {
		return nil, rpcInvalidError("Tx hash does not match: got %v "+
			"expected %v", txHash, mtx.TxHash())
	}

	txReply := &hcjson.TxRawResult{
		Hex:         mtxHex,
		Txid:        txHash,
		Vin:         createVinList(mtx),
		Vout:        createVoutList(mtx, chainParams, nil),
		Version:     int32(mtx.Version),
		LockTime:    mtx.LockTime,
		Expiry:      mtx.Expiry,
		BlockHeight: blkHeight,
		BlockIndex:  blkIdx,
	}

	if blkHeader != nil {
		// This is not a typo, they are identical in bitcoind as well.
		txReply.Time = blkHeader.Timestamp.Unix()
		txReply.Blocktime = blkHeader.Timestamp.Unix()
		txReply.BlockHash = blkHash
		txReply.Confirmations = confirmations
	}

	return txReply, nil
}

// handleDecodeRawTransaction handles decoderawtransaction commands.
func handleDecodeRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.DecodeRawTransactionCmd)

	// Deserialize the transaction.
	hexStr := c.HexTx
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	serializedTx, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, rpcDecodeHexError(hexStr)
	}
	var mtx wire.MsgTx
	err = mtx.Deserialize(bytes.NewReader(serializedTx))
	if err != nil {
		return nil, rpcDeserializationError("Could not decode Tx: %v",
			err)
	}

	// Create and return the result.
	txReply := hcjson.TxRawDecodeResult{
		Txid:     mtx.TxHash().String(),
		Version:  int32(mtx.Version),
		Locktime: mtx.LockTime,
		Expiry:   mtx.Expiry,
		Vin:      createVinList(&mtx),
		Vout:     createVoutList(&mtx, s.server.chainParams, nil),
	}
	return txReply, nil
}

// handleDecodeScript handles decodescript commands.
func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.DecodeScriptCmd)

	// Convert the hex script to bytes.
	hexStr := c.HexScript
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	script, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, rpcDecodeHexError(hexStr)
	}

	// The disassembled string will contain [error] inline if the script
	// doesn't fully parse, so ignore the error here.
	disbuf, _ := txscript.DisasmString(script)

	// Get information about the script.
	// Ignore the error here since an error means the script couldn't parse
	// and there is no additinal information about it anyways.
	// TODO Replace magic version with argument passed to RPC call
	scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
		txscript.DefaultScriptVersion, script, s.server.chainParams)
	addresses := make([]string, len(addrs))
	for i, addr := range addrs {
		addresses[i] = addr.EncodeAddress()
	}

	// Convert the script itself to a pay-to-script-hash address.
	p2sh, err := hcutil.NewAddressScriptHash(script, s.server.chainParams)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Failed to convert script to pay-to-script-hash")
	}

	// Generate and return the reply.
	reply := hcjson.DecodeScriptResult{
		Asm:       disbuf,
		ReqSigs:   int32(reqSigs),
		Type:      scriptClass.String(),
		Addresses: addresses,
		P2sh:      p2sh.EncodeAddress(),
	}
	return reply, nil
}

// handleEstimateFee implenents the estimatefee command.
// TODO this is a very basic implementation.  It should be
// modified to match the bitcoin-core one.
func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return cfg.minRelayTxFee.ToCoin(), nil
}

// handleEstimateStakeDiff implements the estimatestakediff command.
func handleEstimateStakeDiff(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.EstimateStakeDiffCmd)

	// Minimum possible stake difficulty.
	chain := s.server.blockManager.chain
	min, err := chain.EstimateNextStakeDifficulty(0, false)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Could not "+
			"estimate next minimum stake difficulty")
	}

	// Maximum possible stake difficulty.
	max, err := chain.EstimateNextStakeDifficulty(0, true)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Could not "+
			"estimate next maximum stake difficulty")
	}

	// The expected stake difficulty. Average the number of fresh stake
	// since the last retarget to get the number of tickets per block,
	// then use that to estimate the next stake difficulty.
	_, bestHeight := s.server.blockManager.chainState.Best()
	lastAdjustment := (bestHeight / activeNetParams.StakeDiffWindowSize) *
		activeNetParams.StakeDiffWindowSize
	nextAdjustment := ((bestHeight / activeNetParams.StakeDiffWindowSize) +
		1) * activeNetParams.StakeDiffWindowSize
	totalTickets := 0
	err = s.server.db.View(func(dbTx database.Tx) error {
		for i := lastAdjustment; i <= bestHeight; i++ {
			bh, err := blockchain.DBFetchHeaderByHeight(dbTx, i)
			if err != nil {
				return err
			}
			totalTickets += int(bh.FreshStake)
		}

		return nil
	})
	blocksSince := float64(bestHeight - lastAdjustment + 1)
	remaining := float64(nextAdjustment - bestHeight - 1)
	averagePerBlock := float64(totalTickets) / blocksSince
	expectedTickets := int64(math.Floor(averagePerBlock * remaining))
	expected, err := chain.EstimateNextStakeDifficulty(expectedTickets,
		false)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Could not "+
			"estimate next stake difficulty")
	}

	// User-specified stake difficulty, if they asked for one.
	var userEstFltPtr *float64
	if c.Tickets != nil {
		userEst, err := chain.EstimateNextStakeDifficulty(int64(*c.Tickets),
			false)
		if err != nil {
			return nil, rpcInternalError(err.Error(), "Could not "+
				"estimate next user specified stake difficulty")
		}
		userEstFlt := hcutil.Amount(userEst).ToCoin()
		userEstFltPtr = &userEstFlt
	}

	return &hcjson.EstimateStakeDiffResult{
		Min:      hcutil.Amount(min).ToCoin(),
		Max:      hcutil.Amount(max).ToCoin(),
		Expected: hcutil.Amount(expected).ToCoin(),
		User:     userEstFltPtr,
	}, nil
}

// handleExistsAddress implements the existsaddress command.
func handleExistsAddress(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	existsAddrIndex := s.server.existsAddrIndex
	if existsAddrIndex == nil {
		return nil, rpcInternalError("Exists address index disabled",
			"Configuration")
	}

	c := cmd.(*hcjson.ExistsAddressCmd)

	// Attempt to decode the supplied address.
	addr, err := hcutil.DecodeAddress(c.Address)
	if err != nil {
		return nil, rpcAddressKeyError("Could not decode address: %v",
			err)
	}

	exists, err := existsAddrIndex.ExistsAddress(addr)
	if err != nil {
		return nil, rpcInvalidError("Could not query address: %v", err)
	}

	return exists, nil
}

// handleExistsAddresses implements the existsaddresses command.
func handleExistsAddresses(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	existsAddrIndex := s.server.existsAddrIndex
	if existsAddrIndex == nil {
		return nil, rpcInternalError("Exists address index disabled",
			"Configuration")
	}

	c := cmd.(*hcjson.ExistsAddressesCmd)
	addresses := make([]hcutil.Address, len(c.Addresses))
	for i := range c.Addresses {
		// Attempt to decode the supplied address.
		addr, err := hcutil.DecodeAddress(c.Addresses[i])
		if err != nil {
			return nil, rpcAddressKeyError("Could not decode "+
				"address: %v", err)
		}
		addresses[i] = addr
	}

	exists, err := existsAddrIndex.ExistsAddresses(addresses)
	if err != nil {
		return nil, rpcInvalidError("Could not query address: %v", err)
	}

	// Convert the slice of bools into a compacted set of bit flags.
	set := bitset.NewBytes(len(c.Addresses))
	for i := range exists {
		if exists[i] {
			set.Set(i)
		}
	}

	return hex.EncodeToString([]byte(set)), nil
}

// handleExistsMissedTickets implements the existsmissedtickets command.
func handleExistsMissedTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ExistsMissedTicketsCmd)

	hashes, err := hcjson.DecodeConcatenatedHashes(c.TxHashBlob)
	if err != nil {
		return nil, err
	}

	exists := s.server.blockManager.chain.CheckMissedTickets(hashes)
	if len(exists) != len(hashes) {
		return nil, rpcInvalidError("Invalid missed ticket count "+
			"got %v, want %v", len(exists), len(hashes))
	}

	// Convert the slice of bools into a compacted set of bit flags.
	set := bitset.NewBytes(len(hashes))
	for i := range exists {
		if exists[i] {
			set.Set(i)
		}
	}

	return hex.EncodeToString([]byte(set)), nil
}

// handleExistsExpiredTickets implements the existsexpiredtickets command.
func handleExistsExpiredTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ExistsExpiredTicketsCmd)

	hashes, err := hcjson.DecodeConcatenatedHashes(c.TxHashBlob)
	if err != nil {
		return nil, err
	}

	exists := s.server.blockManager.chain.CheckExpiredTickets(hashes)
	if len(exists) != len(hashes) {
		return nil, rpcInvalidError("Invalid expired ticket count "+
			"got %v, want %v", len(exists), len(hashes))
	}

	// Convert the slice of bools into a compacted set of bit flags.
	set := bitset.NewBytes(len(hashes))
	for i := range exists {
		if exists[i] {
			set.Set(i)
		}
	}

	return hex.EncodeToString([]byte(set)), nil
}

// handleExistsLiveTicket implements the existsliveticket command.
func handleExistsLiveTicket(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ExistsLiveTicketCmd)

	hash, err := chainhash.NewHashFromStr(c.TxHash)
	if err != nil {
		return nil, rpcDecodeHexError(c.TxHash)
	}

	return s.server.blockManager.chain.CheckLiveTicket(*hash), nil
}

// handleExistsLiveTickets implements the existslivetickets command.
func handleExistsLiveTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ExistsLiveTicketsCmd)

	hashes, err := hcjson.DecodeConcatenatedHashes(c.TxHashBlob)
	if err != nil {
		return nil, err
	}

	exists := s.server.blockManager.chain.CheckLiveTickets(hashes)
	if len(exists) != len(hashes) {
		return nil, rpcInvalidError("Invalid live ticket count got "+
			"%v, want %v", len(exists), len(hashes))
	}

	// Convert the slice of bools into a compacted set of bit flags.
	set := bitset.NewBytes(len(hashes))
	for i := range exists {
		if exists[i] {
			set.Set(i)
		}
	}

	return hex.EncodeToString([]byte(set)), nil
}

// handleExistsMempoolTxs implements the existsmempooltxs command.
func handleExistsMempoolTxs(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ExistsMempoolTxsCmd)

	txHashBlob, err := hex.DecodeString(c.TxHashBlob)
	if err != nil {
		return nil, rpcDecodeHexError(c.TxHashBlob)
	}

	// It needs to be an exact number of hashes.
	if len(txHashBlob)%32 != 0 {
		return nil, rpcInvalidError("Invalid hash blob length")
	}

	hashesLen := len(txHashBlob) / 32
	hashes := make([]*chainhash.Hash, hashesLen)
	for i := 0; i < hashesLen; i++ {
		hashes[i], err = chainhash.NewHash(
			txHashBlob[i*chainhash.HashSize : (i+1)*chainhash.HashSize])
		if err != nil {
			return nil, rpcInternalError(err.Error(), "New hash")
		}
	}

	exists := s.server.txMemPool.HaveTransactions(hashes)
	if len(exists) != hashesLen {
		return nil, rpcInternalError(fmt.Sprintf("got %v, want %v",
			len(exists), hashesLen),
			"Invalid mempool Tx ticket count")
	}

	// Convert the slice of bools into a compacted set of bit flags.
	set := bitset.NewBytes(hashesLen)
	for i := range exists {
		if exists[i] {
			set.Set(i)
		}
	}

	return hex.EncodeToString([]byte(set)), nil
}

// handleGenerate handles generate commands.
func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// Respond with an error if there are no addresses to pay the
	// created blocks to.
	if len(cfg.miningAddrs) == 0 {
		return nil, rpcInternalError("No payment addresses specified "+
			"via --miningaddr", "Configuration")
	}

	c := cmd.(*hcjson.GenerateCmd)

	// Respond with an error if the client is requesting 0 blocks to be generated.
	if c.NumBlocks == 0 {
		return nil, rpcInternalError("Invalid number of blocks",
			"Configuration")
	}

	// Create a reply
	reply := make([]string, c.NumBlocks)

	blockHashes, err := s.server.cpuMiner.GenerateNBlocks(c.NumBlocks)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Could not generate blocks")
	}

	// Mine the correct number of blocks, assigning the hex representation of the
	// hash of each one to its place in the reply.
	for i, hash := range blockHashes {
		reply[i] = hash.String()
	}

	return reply, nil
}

// handleGetAddedNodeInfo handles getaddednodeinfo commands.
func handleGetAddedNodeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetAddedNodeInfoCmd)

	// Retrieve a list of persistent (added) peers from the HC server
	// and filter the list of peers per the specified address (if any).
	peers := s.server.AddedNodeInfo()
	if c.Node != nil {
		found := false
		for i, peer := range peers {
			if peer.Addr() == *c.Node {
				peers = peers[i : i+1]
				found = true
			}
		}
		if !found {
			return nil, rpcInternalError("Node not found", "")
		}
	}

	// Without the dns flag, the result is just a slice of the addresses as
	// strings.
	if !c.DNS {
		results := make([]string, 0, len(peers))
		for _, peer := range peers {
			results = append(results, peer.Addr())
		}
		return results, nil
	}

	// With the dns flag, the result is an array of JSON objects which
	// include the result of DNS lookups for each peer.
	results := make([]*hcjson.GetAddedNodeInfoResult, 0, len(peers))
	for _, peer := range peers {
		// Set the "address" of the peer which could be an ip address
		// or a domain name.
		var result hcjson.GetAddedNodeInfoResult
		result.AddedNode = peer.Addr()
		result.Connected = hcjson.Bool(peer.Connected())

		// Split the address into host and port portions so we can do a
		// DNS lookup against the host.  When no port is specified in
		// the address, just use the address as the host.
		host, _, err := net.SplitHostPort(peer.Addr())
		if err != nil {
			host = peer.Addr()
		}

		// Do a DNS lookup for the address.  If the lookup fails, just
		// use the host.
		var ipList []string
		ips, err := hcdLookup(host)
		if err == nil {
			ipList = make([]string, 0, len(ips))
			for _, ip := range ips {
				ipList = append(ipList, ip.String())
			}
		} else {
			ipList = make([]string, 1)
			ipList[0] = host
		}

		// Add the addresses and connection info to the result.
		addrs := make([]hcjson.GetAddedNodeInfoResultAddr, 0,
			len(ipList))
		for _, ip := range ipList {
			var addr hcjson.GetAddedNodeInfoResultAddr
			addr.Address = ip
			addr.Connected = "false"
			if ip == host && peer.Connected() {
				addr.Connected = directionString(peer.Inbound())
			}
			addrs = append(addrs, addr)
		}
		result.Addresses = &addrs
		results = append(results, &result)
	}
	return results, nil
}

// handleGetBestBlock implements the getbestblock command.
func handleGetBestBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// All other "get block" commands give either the height, the hash, or
	// both but require the block SHA.  This gets both for the best block.
	best := s.chain.BestSnapshot()
	result := &hcjson.GetBestBlockResult{
		Hash:   best.Hash.String(),
		Height: best.Height,
	}
	return result, nil
}

// handleGetBestBlockHash implements the getbestblockhash command.
func handleGetBestBlockHash(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()
	return best.Hash.String(), nil
}

// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
// minimum difficulty using the passed bits field from the header of a block.
func getDifficultyRatio(bits uint32) float64 {
	// The minimum difficulty is the max possible proof-of-work limit bits
	// converted back to a number.  Note this is not the same as the proof
	// of work limit directly because the block difficulty is encoded in a
	// block with the compact form which loses precision.
	max := blockchain.CompactToBig(activeNetParams.PowLimitBits)
	target := blockchain.CompactToBig(bits)

	difficulty := new(big.Rat).SetFrac(max, target)
	outString := difficulty.FloatString(8)
	diff, err := strconv.ParseFloat(outString, 64)
	if err != nil {
		rpcsLog.Errorf("Cannot get difficulty: %v", err)
		return 0
	}
	return diff
}

// handleGetBlock implements the getblock command.
func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetBlockCmd)

	// Load the raw block bytes from the database.
	hash, err := chainhash.NewHashFromStr(c.Hash)
	if err != nil {
		return nil, rpcDecodeHexError(c.Hash)
	}
	blk, err := s.server.blockManager.chain.FetchBlockByHash(hash)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCBlockNotFound,
			Message: fmt.Sprintf("Block not found: %v", hash),
		}
	}

	// When the verbose flag isn't set, simply return the
	// network-serialized block as a hex-encoded string.
	if c.Verbose != nil && !*c.Verbose {
		blkBytes, err := blk.Bytes()
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not serialize block")
		}

		return hex.EncodeToString(blkBytes), nil
	}

	best := s.chain.BestSnapshot()

	// See if this block is an orphan and adjust Confirmations accordingly.
	onMainChain, _ := s.chain.MainChainHasBlock(hash)

	// Get next block hash unless there are none.
	var nextHashString string
	blockHeader := &blk.MsgBlock().Header
	confirmations := int64(-1)
	if onMainChain {
		if int64(blockHeader.Height) < best.Height {
			nextHash, err := s.chain.BlockHashByHeight(int64(blockHeader.Height + 1))
			if err != nil {
				context := "No next block"
				return nil, rpcInternalError(err.Error(),
					context)
			}
			nextHashString = nextHash.String()
		}
		confirmations = 1 + best.Height - int64(blockHeader.Height)
	}

	sbitsFloat := float64(blockHeader.SBits) / hcutil.AtomsPerCoin
	blockReply := hcjson.GetBlockVerboseResult{
		Hash:          c.Hash,
		Version:       blockHeader.Version,
		MerkleRoot:    blockHeader.MerkleRoot.String(),
		StakeRoot:     blockHeader.StakeRoot.String(),
		PreviousHash:  blockHeader.PrevBlock.String(),
		Nonce:         blockHeader.Nonce,
		VoteBits:      blockHeader.VoteBits,
		FinalState:    hex.EncodeToString(blockHeader.FinalState[:]),
		Voters:        blockHeader.Voters,
		FreshStake:    blockHeader.FreshStake,
		Revocations:   blockHeader.Revocations,
		PoolSize:      blockHeader.PoolSize,
		Time:          blockHeader.Timestamp.Unix(),
		StakeVersion:  blockHeader.StakeVersion,
		Confirmations: confirmations,
		Height:        int64(blockHeader.Height),
		Size:          int32(blk.MsgBlock().Header.Size),
		Bits:          strconv.FormatInt(int64(blockHeader.Bits), 16),
		SBits:         sbitsFloat,
		Difficulty:    getDifficultyRatio(blockHeader.Bits),
		ExtraData:     hex.EncodeToString(blockHeader.ExtraData[:]),
		NextHash:      nextHashString,
	}

	if c.VerboseTx == nil || !*c.VerboseTx {
		transactions := blk.Transactions()
		txNames := make([]string, len(transactions))
		for i, tx := range transactions {
			txNames[i] = tx.Hash().String()
		}

		blockReply.Tx = txNames

		stransactions := blk.STransactions()
		stxNames := make([]string, len(stransactions))
		for i, tx := range stransactions {
			stxNames[i] = tx.Hash().String()
		}

		blockReply.STx = stxNames
	} else {
		txns := blk.Transactions()
		rawTxns := make([]hcjson.TxRawResult, len(txns))
		for i, tx := range txns {
			rawTxn, err := createTxRawResult(s.server.chainParams,
				tx.MsgTx(), tx.Hash().String(), uint32(i),
				blockHeader, blk.Hash().String(),
				int64(blockHeader.Height), confirmations)
			if err != nil {
				return nil, rpcInternalError(err.Error(),
					"Could not create transaction")
			}
			rawTxns[i] = *rawTxn
		}
		blockReply.RawTx = rawTxns

		stxns := blk.STransactions()
		rawSTxns := make([]hcjson.TxRawResult, len(stxns))
		for i, tx := range stxns {
			rawSTxn, err := createTxRawResult(s.server.chainParams,
				tx.MsgTx(), tx.Hash().String(), uint32(i),
				blockHeader, blk.Hash().String(),
				int64(blockHeader.Height), confirmations)
			if err != nil {
				return nil, rpcInternalError(err.Error(),
					"Could not create stake transaction")
			}
			rawSTxns[i] = *rawSTxn
		}
		blockReply.RawSTx = rawSTxns
	}

	return blockReply, nil
}

// handleGetBlockCount implements the getblockcount command.
func handleGetBlockCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()
	return best.Height, nil
}

// handleGetBlockHash implements the getblockhash command.
func handleGetBlockHash(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetBlockHashCmd)
	hash, err := s.chain.BlockHashByHeight(c.Index)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code: hcjson.ErrRPCOutOfRange,
			Message: fmt.Sprintf("Block number out of range: %v",
				c.Index),
		}
	}

	return hash.String(), nil
}

// handleGetBlockHeader implements the getblockheader command.
func handleGetBlockHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetBlockHeaderCmd)

	// Load the raw header bytes from the database.
	hash, err := chainhash.NewHashFromStr(c.Hash)
	if err != nil {
		return nil, rpcDecodeHexError(c.Hash)
	}
	var headerBytes []byte
	err = s.server.db.View(func(dbTx database.Tx) error {
		var err error
		headerBytes, err = dbTx.FetchBlockHeader(hash)
		return err
	})
	if err != nil {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCBlockNotFound,
			Message: fmt.Sprintf("Block not found: %v", c.Hash),
		}
	}

	// When the verbose flag isn't set, simply return the serialized block
	// header as a hex-encoded string.
	if c.Verbose != nil && !*c.Verbose {
		return hex.EncodeToString(headerBytes), nil
	}

	// The verbose flag is set, so generate the JSON object and return it.

	// Deserialize the header.
	var blockHeader wire.BlockHeader
	err = blockHeader.Deserialize(bytes.NewReader(headerBytes))
	if err != nil {
		context := "Could not deserialize block header"
		return nil, rpcInternalError(err.Error(), context)
	}

	best := s.chain.BestSnapshot()

	// See if this block is an orphan and adjust Confirmations accordingly.
	onMainChain, _ := s.chain.MainChainHasBlock(hash)

	// Get next block hash unless there are none.
	var nextHashString string
	confirmations := int64(-1)
	height := int64(blockHeader.Height)
	if onMainChain {
		if height < best.Height {
			nextHash, err := s.chain.BlockHashByHeight(height + 1)
			if err != nil {
				context := "No next block"
				return nil, rpcInternalError(err.Error(),
					context)
			}
			nextHashString = nextHash.String()
		}
		confirmations = 1 + best.Height - height
	}

	blockHeaderReply := hcjson.GetBlockHeaderVerboseResult{
		Hash:          c.Hash,
		Confirmations: confirmations,
		Version:       blockHeader.Version,
		PreviousHash:  blockHeader.PrevBlock.String(),
		MerkleRoot:    blockHeader.MerkleRoot.String(),
		StakeRoot:     blockHeader.StakeRoot.String(),
		VoteBits:      blockHeader.VoteBits,
		FinalState:    hex.EncodeToString(blockHeader.FinalState[:]),
		Voters:        blockHeader.Voters,
		FreshStake:    blockHeader.FreshStake,
		Revocations:   blockHeader.Revocations,
		PoolSize:      blockHeader.PoolSize,
		Bits:          strconv.FormatInt(int64(blockHeader.Bits), 16),
		SBits:         hcutil.Amount(blockHeader.SBits).ToCoin(),
		Height:        uint32(height),
		Size:          blockHeader.Size,
		Time:          blockHeader.Timestamp.Unix(),
		Nonce:         blockHeader.Nonce,
		StakeVersion:  blockHeader.StakeVersion,
		Difficulty:    getDifficultyRatio(blockHeader.Bits),
		NextHash:      nextHashString,
	}

	return blockHeaderReply, nil

}

// handleGetBlockSubsidy implements the getblocksubsidy command.
func handleGetBlockSubsidy(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetBlockSubsidyCmd)

	height := c.Height
	voters := c.Voters

	cache := s.chain.FetchSubsidyCache()
	if cache == nil {
		return nil, rpcInternalError("empty subsidy cache", "")
	}

	dev := blockchain.CalcBlockTaxSubsidy(cache, height, voters,
		s.server.chainParams)
	pos := blockchain.CalcStakeVoteSubsidy(cache, height,
		s.server.chainParams) * int64(voters)
	pow := blockchain.CalcBlockWorkSubsidy(cache, height, voters,
		s.server.chainParams)
	total := dev + pos + pow

	rep := hcjson.GetBlockSubsidyResult{
		Developer: dev,
		PoS:       pos,
		PoW:       pow,
		Total:     total,
	}

	return rep, nil
}

// encodeTemplateID encodes the passed details into an ID that can be used to
// uniquely identify a block template.
func encodeTemplateID(prevHash *chainhash.Hash, lastGenerated time.Time) string {
	return fmt.Sprintf("%s-%d", prevHash.String(), lastGenerated.Unix())
}

// decodeTemplateID decodes an ID that is used to uniquely identify a block
// template.  This is mainly used as a mechanism to track when to update
// clients that are using long polling for block templates.  The ID consists of
// the previous block hash for the associated template and the time the
// associated template was generated.
func decodeTemplateID(templateID string) (*chainhash.Hash, int64, error) {
	fields := strings.Split(templateID, "-")
	if len(fields) != 2 {
		return nil, 0, ErrInvalidLongPoll
	}

	prevHash, err := chainhash.NewHashFromStr(fields[0])
	if err != nil {
		return nil, 0, ErrInvalidLongPoll
	}
	lastGenerated, err := strconv.ParseInt(fields[1], 10, 64)
	if err != nil {
		return nil, 0, ErrInvalidLongPoll
	}

	return prevHash, lastGenerated, nil
}

// notifyLongPollers notifies any channels that have been registered to be
// notified when block templates are stale.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) notifyLongPollers(latestHash *chainhash.Hash, lastGenerated time.Time) {
	// Notify anything that is waiting for a block template update from a
	// hash which is not the hash of the tip of the best chain since their
	// work is now invalid.
	for hash, channels := range state.notifyMap {
		if !hash.IsEqual(latestHash) {
			for _, c := range channels {
				close(c)
			}
			delete(state.notifyMap, hash)
		}
	}

	// Return now if the provided last generated timestamp has not been
	// initialized.
	if lastGenerated.IsZero() {
		return
	}

	// Return now if there is nothing registered for updates to the current
	// best block hash.
	channels, ok := state.notifyMap[*latestHash]
	if !ok {
		return
	}

	// Notify anything that is waiting for a block template update from a
	// block template generated before the most recently generated block
	// template.
	lastGeneratedUnix := lastGenerated.Unix()
	for lastGen, c := range channels {
		if lastGen < lastGeneratedUnix {
			close(c)
			delete(channels, lastGen)
		}
	}

	// Remove the entry altogether if there are no more registered
	// channels.
	if len(channels) == 0 {
		delete(state.notifyMap, *latestHash)
	}
}

// NotifyBlockConnected uses the newly-connected block to notify any long poll
// clients with a new block template when their existing block template is
// stale due to the newly connected block.
func (state *gbtWorkState) NotifyBlockConnected(blockHash *chainhash.Hash) {
	go func() {
		state.Lock()
		defer state.Unlock()

		state.notifyLongPollers(blockHash, state.lastTxUpdate)
	}()
}

// NotifyMempoolTx uses the new last updated time for the transaction memory
// pool to notify any long poll clients with a new block template when their
// existing block template is stale due to enough time passing and the contents
// of the memory pool changing.
func (state *gbtWorkState) NotifyMempoolTx(lastUpdated time.Time) {
	go func() {
		state.Lock()
		defer state.Unlock()

		// No need to notify anything if no block templates have been generated
		// yet.
		if state.prevHash == nil || state.lastGenerated.IsZero() {
			return
		}

		if time.Now().After(state.lastGenerated.Add(time.Second *
			gbtRegenerateSeconds)) {

			state.notifyLongPollers(state.prevHash, lastUpdated)
		}
	}()
}

// templateUpdateChan returns a channel that will be closed once the block
// template associated with the passed previous hash and last generated time
// is stale.  The function will return existing channels for duplicate
// parameters which allows multiple clients to wait for the same block template
// without requiring a different channel for each client.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) templateUpdateChan(prevHash *chainhash.Hash, lastGenerated int64) chan struct{} {
	// Either get the current list of channels waiting for updates about
	// changes to block template for the previous hash or create a new one.
	channels, ok := state.notifyMap[*prevHash]
	if !ok {
		m := make(map[int64]chan struct{})
		state.notifyMap[*prevHash] = m
		channels = m
	}

	// Get the current channel associated with the time the block template
	// was last generated or create a new one.
	c, ok := channels[lastGenerated]
	if !ok {
		c = make(chan struct{})
		channels[lastGenerated] = c
	}

	return c
}

// updateBlockTemplate creates or updates a block template for the work state.
// A new block template will be generated when the current best block has
// changed or the transactions in the memory pool have been updated and it has
// been long enough since the last template was generated.  Otherwise, the
// timestamp for the existing block template is updated (and possibly the
// difficulty on testnet per the consesus rules).  Finally, if the
// useCoinbaseValue flag is false and the existing block template does not
// already contain a valid payment address, the block template will be updated
// with a randomly selected payment address from the list of configured
// addresses.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bool) error {
	lastTxUpdate := s.server.txMemPool.LastUpdated()
	if lastTxUpdate.IsZero() {
		lastTxUpdate = time.Now()
	}

	// Generate a new block template when the current best block has
	// changed or the transactions in the memory pool have been updated and
	// it has been at least gbtRegenerateSecond since the last template was
	// generated.
	var msgBlock *wire.MsgBlock
	var targetDifficulty string
	latestHash, _ := s.server.blockManager.chainState.Best()
	template := state.template
	if template == nil || state.prevHash == nil ||
		!state.prevHash.IsEqual(latestHash) ||
		(state.lastTxUpdate != lastTxUpdate &&
			time.Now().After(state.lastGenerated.Add(time.Second*
				gbtRegenerateSeconds))) {

		// Reset the previous best hash the block template was generated
		// against so any errors below cause the next invocation to try
		// again.
		state.prevHash = nil

		// Choose a payment address at random if the caller requests a
		// full coinbase as opposed to only the pertinent details needed
		// to create their own coinbase.
		var payAddr hcutil.Address
		if !useCoinbaseValue {
			payAddr = cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
		}

		// Create a new block template that has a coinbase which anyone
		// can redeem.  This is only acceptable because the returned
		// block template doesn't include the coinbase, so the caller
		// will ultimately create their own coinbase which pays to the
		// appropriate address(es).
		blkTemplate, err := NewBlockTemplate(s.policy, s.server, payAddr)
		if err != nil {
			return rpcInternalError("Failed to create new block "+
				"template: "+err.Error(), "")
		}
		if blkTemplate == nil {
			return rpcInternalError("Failed to create new block "+
				"template: not enough voters on parent and no "+
				"suitable cached template", "")
		}
		template = blkTemplate
		msgBlock = template.Block
		targetDifficulty = fmt.Sprintf("%064x",
			blockchain.CompactToBig(msgBlock.Header.Bits))

		// Find the minimum allowed timestamp for the block based on the
		// median timestamp of the last several blocks per the chain
		// consensus rules.
		chainState := &s.server.blockManager.chainState
		minTimestamp, err := minimumMedianTime(chainState)
		if err != nil {
			context := "Failed to get minimum median time"
			return rpcInternalError(err.Error(), context)
		}

		// Update work state to ensure another block template isn't
		// generated until needed.
		state.template = deepCopyBlockTemplate(template)
		state.lastGenerated = time.Now()
		state.lastTxUpdate = lastTxUpdate
		state.prevHash = latestHash
		state.minTimestamp = minTimestamp

		rpcsLog.Debugf("Generated block template (timestamp %v, "+
			"target %s, merkle root %s)",
			msgBlock.Header.Timestamp, targetDifficulty,
			msgBlock.Header.MerkleRoot)

		// Notify any clients that are long polling about the new
		// template.
		state.notifyLongPollers(latestHash, lastTxUpdate)
	} else {
		// At this point, there is a saved block template and another
		// request for a template was made, but either the available
		// transactions haven't change or it hasn't been long enough to
		// trigger a new block template to be generated.  So, update the
		// existing block template.

		// When the caller requires a full coinbase as opposed to only
		// the pertinent details needed to create their own coinbase,
		// add a payment address to the output of the coinbase of the
		// template if it doesn't already have one.  Since this requires
		// mining addresses to be specified via the config, an error is
		// returned if none have been specified.
		if !useCoinbaseValue && !template.ValidPayAddress {
			// Choose a payment address at random.
			payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]

			// Update the block coinbase output of the template to
			// pay to the randomly selected payment address.
			pkScript, err := txscript.PayToAddrScript(payToAddr)
			if err != nil {
				context := "Failed to create pay-to-addr script"
				return rpcInternalError(err.Error(), context)
			}
			template.Block.Transactions[0].TxOut[0].PkScript = pkScript
			template.ValidPayAddress = true

			// Update the merkle root.
			block := hcutil.NewBlock(template.Block)
			merkles := blockchain.BuildMerkleTreeStore(block.Transactions())
			template.Block.Header.MerkleRoot = *merkles[len(merkles)-1]
		}

		// Set locals for convenience.
		msgBlock = template.Block
		targetDifficulty = fmt.Sprintf("%064x",
			blockchain.CompactToBig(msgBlock.Header.Bits))

		// Update the time of the block template to the current time
		// while accounting for the median time of the past several
		// blocks per the chain consensus rules.
		err := UpdateBlockTime(msgBlock, s.server.blockManager)
		if err != nil {
			context := "Failed to update timestamp"
			return rpcInternalError(err.Error(), context)
		}
		msgBlock.Header.Nonce = 0

		rpcsLog.Debugf("Updated block template (timestamp %v, "+
			"target %s)", msgBlock.Header.Timestamp,
			targetDifficulty)
	}

	return nil
}

// blockTemplateResult returns the current block template associated with the
// state as a hcjson.GetBlockTemplateResult that is ready to be encoded to
// JSON and returned to the caller.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) blockTemplateResult(bm *blockManager, useCoinbaseValue bool, submitOld *bool) (*hcjson.GetBlockTemplateResult, error) {
	// Ensure the timestamps are still in valid range for the template.
	// This should really only ever happen if the local clock is changed
	// after the template is generated, but it's important to avoid serving
	// invalid block templates.
	template := deepCopyBlockTemplate(state.template)
	msgBlock := template.Block
	header := &msgBlock.Header
	adjustedTime := state.timeSource.AdjustedTime()
	maxTime := adjustedTime.Add(time.Second * blockchain.MaxTimeOffsetSeconds)
	if header.Timestamp.After(maxTime) {
		return nil, &hcjson.RPCError{
			Code: hcjson.ErrRPCOutOfRange,
			Message: fmt.Sprintf("The template time is after the "+
				"maximum allowed time for a block - template "+
				"time %v, maximum time %v", adjustedTime,
				maxTime),
		}

	}

	// Sometimes requests have a faulty fees or sig ops count. If we need to,
	// we can recalculate these.
	recalculateFeesAndSigsOps := true
	if len(msgBlock.Transactions)+len(msgBlock.STransactions) ==
		len(template.Fees) {
		recalculateFeesAndSigsOps = false
	}
	if len(msgBlock.Transactions)+len(msgBlock.STransactions) ==
		len(template.SigOpCounts) {
		recalculateFeesAndSigsOps = false
	}
	newestBlock, _ := bm.chainState.Best()
	if newestBlock == nil {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCBestBlockHash,
			Message: fmt.Sprintf("Parent of block HEAD not found"),
		}
	}
	// If we're mining on the parent with a cached template instead of on
	// the newest block, we shouldn't recalculate fees and sigops.
	if *newestBlock != msgBlock.Header.PrevBlock {
		recalculateFeesAndSigsOps = false
	}

	// Convert each transaction in the block template to a template result
	// transaction.  The result does not include the coinbase, so notice
	// the adjustments to the various lengths and indices.
	numTx := len(msgBlock.Transactions)
	transactions := make([]hcjson.GetBlockTemplateResultTx, 0, numTx-1)
	txIndex := make(map[chainhash.Hash]int64, numTx)
	for i, tx := range msgBlock.Transactions {
		txHash := tx.TxHashFull()
		txIndex[txHash] = int64(i)

		// Skip the coinbase transaction.
		if i == 0 {
			continue
		}

		// Create an array of 1-based indices to transactions that come
		// before this one in the transactions list which this one
		// depends on.  This is necessary since the created block must
		// ensure proper ordering of the dependencies.  A map is used
		// before creating the final array to prevent duplicate entries
		// when multiple inputs reference the same transaction.
		dependsMap := make(map[int64]struct{})
		for _, txIn := range tx.TxIn {
			if idx, ok := txIndex[txIn.PreviousOutPoint.Hash]; ok {
				dependsMap[idx] = struct{}{}
			}
		}
		depends := make([]int64, 0, len(dependsMap))
		for idx := range dependsMap {
			depends = append(depends, idx)
		}

		// Serialize the transaction for later conversion to hex.
		txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(txBuf); err != nil {
			context := "Failed to serialize transaction"
			return nil, rpcInternalError(err.Error(), context)
		}

		var txTypeStr string
		txType := stake.DetermineTxType(tx)
		switch txType {
		case stake.TxTypeRegular:
			txTypeStr = "regular"
		case stake.TxTypeSStx:
			txTypeStr = "error"
		case stake.TxTypeSSGen:
			txTypeStr = "error"
		case stake.TxTypeSSRtx:
			txTypeStr = "error"
		}

		fee := int64(0)
		sigOps := int64(0)
		if !recalculateFeesAndSigsOps {
			fee = template.Fees[i]
			sigOps = template.SigOpCounts[i]
		} else {
			txU := hcutil.NewTx(tx)
			isValid := hcutil.IsFlagSet16(
				template.Block.Header.VoteBits,
				hcutil.BlockValid)
			view, err := bm.chain.FetchUtxoView(txU, isValid)
			if err != nil {
				context := "Could not fetch Utxo view"
				return nil, rpcInternalError(err.Error(),
					context)
			}

			fee, err = blockchain.CheckTransactionInputs(
				bm.chain.FetchSubsidyCache(),
				txU,
				int64(template.Block.Header.Height),
				view,
				true, // Ensure fraud proofs are correct
				bm.server.chainParams)
			if err != nil {
				context := "Invalid transaction inputs"
				return nil, rpcInternalError(err.Error(),
					context)
			}

			isSSGen := false
			numSigOps, err := blockchain.CountP2SHSigOps(txU, false,
				isSSGen, view)
			if err != nil {
				context := "Could not count sig ops"
				return nil, rpcInternalError(err.Error(),
					context)
			}

			numSigOps += blockchain.CountSigOps(txU, false,
				isSSGen)
			if numSigOps > maxSigOpsPerTx {
				errStr := fmt.Sprintf("transaction %v has "+
					"too many sigops: %d > %d", txHash,
					numSigOps, maxSigOpsPerTx)
				return nil, rpcInternalError(errStr, "")
			}
			sigOps = int64(numSigOps)
		}

		resultTx := hcjson.GetBlockTemplateResultTx{
			Data:    hex.EncodeToString(txBuf.Bytes()),
			Hash:    txHash.String(),
			Depends: depends,
			Fee:     fee,
			SigOps:  sigOps,
			TxType:  txTypeStr,
		}
		transactions = append(transactions, resultTx)
	}

	// Convert each stake transaction in the block template to a template
	// result transaction.
	numSTx := len(msgBlock.STransactions)
	stransactions := make([]hcjson.GetBlockTemplateResultTx, 0, numSTx)
	stxIndex := make(map[chainhash.Hash]int64, numSTx)
	for i, stx := range msgBlock.STransactions {
		stxHash := stx.TxHashFull()

		stxIndex[stxHash] = int64(i)

		// Create an array of 1-based indices to transactions that come
		// before this one in the transactions list which this one
		// depends on.  This is necessary since the created block must
		// ensure proper ordering of the dependencies.  A map is used
		// before creating the final array to prevent duplicate entries
		// when mutiple inputs reference the same transaction.
		dependsMap := make(map[int64]struct{})
		for _, txIn := range stx.TxIn {
			if idx, ok := stxIndex[txIn.PreviousOutPoint.Hash]; ok {
				dependsMap[idx] = struct{}{}
			}
		}
		depends := make([]int64, 0, len(dependsMap))
		for idx := range dependsMap {
			depends = append(depends, idx)
		}

		// Serialize the transaction for later conversion to hex.
		txBuf := bytes.NewBuffer(make([]byte, 0, stx.SerializeSize()))
		if err := stx.Serialize(txBuf); err != nil {
			return nil, err
		}

		var txTypeStr string
		txType := stake.DetermineTxType(stx)
		switch txType {
		case stake.TxTypeRegular:
			txTypeStr = "error"
		case stake.TxTypeSStx:
			txTypeStr = "ticket"
		case stake.TxTypeSSGen:
			txTypeStr = "vote"
		case stake.TxTypeSSRtx:
			txTypeStr = "revocation"
		}

		fee := int64(0)
		sigOps := int64(0)
		if !recalculateFeesAndSigsOps {
			// Check bounds and throw an error if OOB. This should
			// be looked into further, probably it's the result of
			// a race.
			// Hcd TODO
			allTxCount := len(msgBlock.Transactions) +
				len(msgBlock.STransactions)
			if allTxCount != len(template.Fees) ||
				allTxCount != len(template.SigOpCounts) {
				errStr := "failed to build template due to " +
					"race"
				return nil, rpcInternalError(errStr, "")
			}

			fee = template.Fees[i+len(msgBlock.Transactions)]
			sigOps = template.SigOpCounts[i+len(msgBlock.Transactions)]
		} else {
			txU := hcutil.NewTx(stx)
			isValid := hcutil.IsFlagSet16(
				template.Block.Header.VoteBits,
				hcutil.BlockValid)
			view, err := bm.chain.FetchUtxoView(txU, isValid)
			if err != nil {
				return nil, err
			}

			fee, err = blockchain.CheckTransactionInputs(
				bm.chain.FetchSubsidyCache(),
				txU,
				int64(template.Block.Header.Height),
				view,
				true, // Ensure fraud proofs are correct
				bm.server.chainParams)
			if err != nil {
				context := "Could not fetch transaction " +
					"inputs"
				return nil, rpcInternalError(err.Error(),
					context)
			}

			isSSGen := txType == stake.TxTypeSSGen
			numSigOps, err := blockchain.CountP2SHSigOps(txU,
				false, isSSGen,
				view)
			if err != nil {
				context := "Could not count sig ops "
				return nil, rpcInternalError(err.Error(),
					context)
			}

			numSigOps += blockchain.CountSigOps(txU, false, isSSGen)
			if numSigOps > maxSigOpsPerTx {
				errStr := fmt.Sprintf("transaction %v has "+
					"too many sigops: %d > %d", stxHash,
					numSigOps, maxSigOpsPerTx)
				return nil, rpcInternalError(errStr, "")
			}
			sigOps = int64(numSigOps)
		}

		resultTx := hcjson.GetBlockTemplateResultTx{
			Data:    hex.EncodeToString(txBuf.Bytes()),
			Hash:    stxHash.String(),
			Depends: depends,
			Fee:     fee,
			SigOps:  sigOps,
			TxType:  txTypeStr,
		}
		stransactions = append(stransactions, resultTx)
	}

	headerBytes, err := header.Bytes()
	if err != nil {
		context := "Could not obtain header"
		return nil, rpcInternalError(err.Error(), context)
	}

	// Choose the correct maximum block size as defined by the  network
	// parameters and the current status of any hard fork votes to change
	// it when serialized.
	maxBlockSize, err := bm.chain.MaxBlockSize()
	if err != nil {
		context := "Invalid blocksize"
		return nil, rpcInternalError(err.Error(), context)
	}

	// Generate the block template reply.  Note that following mutations
	// are implied by the included or omission of fields:
	//  Including MinTime -> time/decrement
	//  Omitting CoinbaseTxn -> coinbase, generation
	targetDifficulty := fmt.Sprintf("%064x", blockchain.CompactToBig(header.Bits))
	templateID := encodeTemplateID(state.prevHash, state.lastGenerated)
	reply := hcjson.GetBlockTemplateResult{
		Header:        hex.EncodeToString(headerBytes),
		SigOpLimit:    blockchain.MaxSigOpsPerBlock,
		SizeLimit:     maxBlockSize,
		Transactions:  transactions,
		STransactions: stransactions,
		LongPollID:    templateID,
		SubmitOld:     submitOld,
		Target:        targetDifficulty,
		MinTime:       state.minTimestamp.Unix(),
		MaxTime:       maxTime.Unix(),
		Mutable:       gbtMutableFields,
		NonceRange:    gbtNonceRange,
		Capabilities:  gbtCapabilities,
	}
	if useCoinbaseValue {
		reply.CoinbaseAux = gbtCoinbaseAux
		reply.CoinbaseValue = &msgBlock.Transactions[0].TxOut[0].Value
	} else {
		// Ensure the template has a valid payment address associated
		// with it when a full coinbase is requested.
		if !template.ValidPayAddress {
			context := "Invalid blocksize"
			errStr := fmt.Sprintf("A coinbase transaction has " +
				"been requested, but the server has not " +
				"been configured with any payment " +
				"addresses via --miningaddr")
			return nil, rpcInternalError(errStr, context)
		}

		// Serialize the transaction for conversion to hex.
		tx := msgBlock.Transactions[0]
		txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(txBuf); err != nil {
			context := "Could not serialize"
			return nil, rpcInternalError(err.Error(), context)
		}

		resultTx := hcjson.GetBlockTemplateResultTx{
			Data:    hex.EncodeToString(txBuf.Bytes()),
			Hash:    tx.TxHash().String(),
			Depends: []int64{},
			Fee:     template.Fees[0],
			SigOps:  template.SigOpCounts[0],
		}

		reply.CoinbaseTxn = &resultTx
	}

	return &reply, nil
}

// handleGetBlockTemplateLongPoll is a helper for handleGetBlockTemplateRequest
// which deals with handling long polling for block templates.  When a caller
// sends a request with a long poll ID that was previously returned, a response
// is not sent until the caller should stop working on the previous block
// template in favor of the new one.  In particular, this is the case when the
// old block template is no longer valid due to a solution already being found
// and added to the block chain, or new transactions have shown up and some time
// has passed without finding a solution.
//
// See https://en.bitcoin.it/wiki/BIP_0022 for more details.
func handleGetBlockTemplateLongPoll(s *rpcServer, longPollID string, useCoinbaseValue bool, closeChan <-chan struct{}) (interface{}, error) {
	state := s.gbtWorkState
	state.Lock()
	// The state unlock is intentionally not deferred here since it needs to
	// be manually unlocked before waiting for a notification about block
	// template changes.

	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		state.Unlock()
		return nil, err
	}

	// Just return the current block template if the long poll ID provided by
	// the caller is invalid.
	prevHash, lastGenerated, err := decodeTemplateID(longPollID)
	if err != nil {
		result, err := state.blockTemplateResult(s.server.blockManager,
			useCoinbaseValue, nil)
		if err != nil {
			state.Unlock()
			return nil, err
		}

		state.Unlock()
		return result, nil
	}

	// Return the block template now if the specific block template
	// identified by the long poll ID no longer matches the current block
	// template as this means the provided template is stale.
	prevTemplateHash := &state.template.Block.Header.PrevBlock
	if !prevHash.IsEqual(prevTemplateHash) ||
		lastGenerated != state.lastGenerated.Unix() {

		// Include whether or not it is valid to submit work against the
		// old block template depending on whether or not a solution has
		// already been found and added to the block chain.
		submitOld := prevHash.IsEqual(prevTemplateHash)
		result, err := state.blockTemplateResult(s.server.blockManager,
			useCoinbaseValue, &submitOld)
		if err != nil {
			state.Unlock()
			return nil, err
		}

		state.Unlock()
		return result, nil
	}

	// Register the previous hash and last generated time for notifications
	// Get a channel that will be notified when the template associated with
	// the provided ID is stale and a new block template should be returned to
	// the caller.
	longPollChan := state.templateUpdateChan(prevHash, lastGenerated)
	state.Unlock()

	select {
	// When the client closes before it's time to send a reply, just return
	// now so the goroutine doesn't hang around.
	case <-closeChan:
		return nil, ErrClientQuit

		// Wait until signal received to send the reply.
	case <-longPollChan:
		// Fallthrough
	}

	// Get the lastest block template
	state.Lock()
	defer state.Unlock()

	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		return nil, err
	}

	// Include whether or not it is valid to submit work against the old
	// block template depending on whether or not a solution has already
	// been found and added to the block chain.
	submitOld := prevHash.IsEqual(&state.template.Block.Header.PrevBlock)
	result, err := state.blockTemplateResult(s.server.blockManager,
		useCoinbaseValue, &submitOld)
	if err != nil {
		return nil, err
	}

	return result, nil
}

// handleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which
// deals with generating and returning block templates to the caller.  It
// handles both long poll requests as specified by BIP 0022 as well as regular
// requests.  In addition, it detects the capabilities reported by the caller
// in regards to whether or not it supports creating its own coinbase (the
// coinbasetxn and coinbasevalue capabilities) and modifies the returned block
// template accordingly.
func handleGetBlockTemplateRequest(s *rpcServer, request *hcjson.TemplateRequest, closeChan <-chan struct{}) (interface{}, error) {
	// Extract the relevant passed capabilities and restrict the result to
	// either a coinbase value or a coinbase transaction object depending
	// on the request.  Default to only providing a coinbase value.
	useCoinbaseValue := true
	if request != nil {
		var hasCoinbaseValue, hasCoinbaseTxn bool
		for _, capability := range request.Capabilities {
			switch capability {
			case "coinbasetxn":
				hasCoinbaseTxn = true
			case "coinbasevalue":
				hasCoinbaseValue = true
			}
		}

		if hasCoinbaseTxn && !hasCoinbaseValue {
			useCoinbaseValue = false
		}
	}

	// When a coinbase transaction has been requested, respond with an
	// error if there are no addresses to pay the created block template
	// to.
	if !useCoinbaseValue && len(cfg.miningAddrs) == 0 {
		return nil, rpcInternalError("A coinbase transaction has "+
			"been requested, but the server has not been "+
			"configured with any payment addresses via "+
			"--miningaddr", "Configuration")
	}

	// Return an error if there are no peers connected since there is no
	// way to relay a found block or receive transactions to work on.
	// However, allow this state when running in the regression test or
	// simulation test mode.
	if !cfg.SimNet && s.server.ConnectedCount() == 0 {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCClientNotConnected,
			Message: "Hcd is not connected",
		}
	}

	// No point in generating or accepting work before the chain is synced.
	_, currentHeight := s.server.blockManager.chainState.Best()
	if currentHeight != 0 && !s.server.blockManager.IsCurrent() {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCClientInInitialDownload,
			Message: "Hcd is downloading blocks...",
		}
	}

	// When a long poll ID was provided, this is a long poll request by the
	// client to be notified when block template referenced by the ID
	// should be replaced with a new one.
	if request != nil && request.LongPollID != "" {
		return handleGetBlockTemplateLongPoll(s, request.LongPollID,
			useCoinbaseValue, closeChan)
	}

	// Protect concurrent access when updating block templates.
	state := s.gbtWorkState
	state.Lock()
	defer state.Unlock()

	// Get and return a block template.  A new block template will be
	// generated when the current best block has changed or the
	// transactions in the memory pool have been updated and it has been at
	// least five seconds since the last template was generated.
	// Otherwise, the timestamp for the existing block template is updated
	// (and possibly the difficulty on testnet per the consesus rules).
	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		return nil, err
	}
	return state.blockTemplateResult(s.server.blockManager, useCoinbaseValue, nil)
}

// chainErrToGBTErrString converts an error returned from chain to a string
// which matches the reasons and format described in BIP0022 for rejection
// reasons.
// TODO Hcd pop in the new errors from blockchain cj
func chainErrToGBTErrString(err error) string {
	// When the passed error is not a RuleError, just return a generic
	// rejected string with the error text.
	ruleErr, ok := err.(blockchain.RuleError)
	if !ok {
		return "rejected: " + err.Error()
	}

	switch ruleErr.ErrorCode {
	case blockchain.ErrDuplicateBlock:
		return "duplicate"
	case blockchain.ErrBlockTooBig:
		return "bad-block-size"
	case blockchain.ErrBlockVersionTooOld:
		return "bad-version"
	case blockchain.ErrInvalidTime:
		return "bad-time"
	case blockchain.ErrTimeTooOld:
		return "time-too-old"
	case blockchain.ErrTimeTooNew:
		return "time-too-new"
	case blockchain.ErrDifficultyTooLow:
		return "bad-diffbits"
	case blockchain.ErrUnexpectedDifficulty:
		return "bad-diffbits"
	case blockchain.ErrHighHash:
		return "high-hash"
	case blockchain.ErrBadMerkleRoot:
		return "bad-txnmrklroot"
	case blockchain.ErrBadCheckpoint:
		return "bad-checkpoint"
	case blockchain.ErrForkTooOld:
		return "fork-too-old"
	case blockchain.ErrCheckpointTimeTooOld:
		return "checkpoint-time-too-old"
	case blockchain.ErrNoTransactions:
		return "bad-txns-none"
	case blockchain.ErrTooManyTransactions:
		return "bad-txns-toomany"
	case blockchain.ErrNoTxInputs:
		return "bad-txns-noinputs"
	case blockchain.ErrNoTxOutputs:
		return "bad-txns-nooutputs"
	case blockchain.ErrTxTooBig:
		return "bad-txns-size"
	case blockchain.ErrBadTxOutValue:
		return "bad-txns-outputvalue"
	case blockchain.ErrDuplicateTxInputs:
		return "bad-txns-dupinputs"
	case blockchain.ErrBadTxInput:
		return "bad-txns-badinput"
	case blockchain.ErrMissingTx:
		return "bad-txns-missinginput"
	case blockchain.ErrUnfinalizedTx:
		return "bad-txns-unfinalizedtx"
	case blockchain.ErrDuplicateTx:
		return "bad-txns-duplicate"
	case blockchain.ErrOverwriteTx:
		return "bad-txns-overwrite"
	case blockchain.ErrImmatureSpend:
		return "bad-txns-maturity"
	case blockchain.ErrDoubleSpend:
		return "bad-txns-dblspend"
	case blockchain.ErrSpendTooHigh:
		return "bad-txns-highspend"
	case blockchain.ErrBadFees:
		return "bad-txns-fees"
	case blockchain.ErrTooManySigOps:
		return "high-sigops"
	case blockchain.ErrFirstTxNotCoinbase:
		return "bad-txns-nocoinbase"
	case blockchain.ErrMultipleCoinbases:
		return "bad-txns-multicoinbase"
	case blockchain.ErrBadCoinbaseScriptLen:
		return "bad-cb-length"
	case blockchain.ErrBadCoinbaseValue:
		return "bad-cb-value"
	case blockchain.ErrScriptMalformed:
		return "bad-script-malformed"
	case blockchain.ErrScriptValidation:
		return "bad-script-validate"
	}

	return "rejected: " + err.Error()
}

// handleGetBlockTemplateProposal is a helper for handleGetBlockTemplate which
// deals with block proposals.
//
// See https://en.bitcoin.it/wiki/BIP_0023 for more details.
func handleGetBlockTemplateProposal(s *rpcServer, request *hcjson.TemplateRequest) (interface{}, error) {
	hexData := request.Data
	if hexData == "" {
		return false, rpcInvalidError("Data must contain the " +
			"hex-encoded serialized block that is being " +
			"proposed")
	}

	// Ensure the provided data is sane and deserialize the proposed block.
	if len(hexData)%2 != 0 {
		hexData = "0" + hexData
	}
	dataBytes, err := hex.DecodeString(hexData)
	if err != nil {
		return false, rpcDecodeHexError(hexData)
	}
	var msgBlock wire.MsgBlock
	if err := msgBlock.Deserialize(bytes.NewReader(dataBytes)); err != nil {
		return nil, rpcDeserializationError("Could not decode block: "+
			"%v", err)
	}
	block := hcutil.NewBlock(&msgBlock)

	// Ensure the block is building from the expected previous block.
	expectedPrevHash, _ := s.server.blockManager.chainState.Best()
	prevHash := &block.MsgBlock().Header.PrevBlock
	if expectedPrevHash == nil || !expectedPrevHash.IsEqual(prevHash) {
		return "bad-prevblk", nil
	}

	flags := blockchain.BFDryRun | blockchain.BFNoPoWCheck
	isOrphan, err := s.server.blockManager.ProcessBlock(block, flags)
	if err != nil {
		if _, ok := err.(blockchain.RuleError); !ok {
			errStr := fmt.Sprintf("Failed to process block "+
				"proposal: %v", err)
			rpcsLog.Error(errStr)
			return nil, rpcInternalError(err.Error(),
				"Could not process block")
		}

		rpcsLog.Infof("Rejected block proposal: %v", err)
		return chainErrToGBTErrString(err), nil
	}
	if isOrphan {
		return "orphan", nil
	}

	return nil, nil
}

// handleGetBlockTemplate implements the getblocktemplate command.
//
// See https://en.bitcoin.it/wiki/BIP_0022 and
// https://en.bitcoin.it/wiki/BIP_0023 for more details.
func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	if s.server.cpuMiner.IsMining() {
		return nil, rpcMiscError("Block template production is " +
			"disallowed while CPU mining is enabled. " +
			"Please disable CPU mining and try again.")
	}

	// Respond with an error if there are no addresses to pay the created
	// blocks to.
	if len(cfg.miningAddrs) == 0 {
		return nil, rpcInternalError("No payment addresses specified "+
			"via --miningaddr", "Configuration")
	}

	c := cmd.(*hcjson.GetBlockTemplateCmd)
	request := c.Request

	// Set the default mode and override it if supplied.
	mode := "template"
	if request != nil && request.Mode != "" {
		mode = request.Mode
	}

	switch mode {
	case "template":
		return handleGetBlockTemplateRequest(s, request, closeChan)
	case "proposal":
		return handleGetBlockTemplateProposal(s, request)
	}

	return nil, rpcInvalidError("Invalid mode: %v", mode)
}

// handleGetCoinSupply implements the getcoinsupply command.
func handleGetCoinSupply(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return s.chain.TotalSubsidy(), nil
}

// handleGetConnectionCount implements the getconnectioncount command.
func handleGetConnectionCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.ConnectedCount(), nil
}

// handleGetCurrentNet implements the getcurrentnet command.
func handleGetCurrentNet(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.chainParams.Net, nil
}

// handleGetDifficulty implements the getdifficulty command.
func handleGetDifficulty(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()
	return getDifficultyRatio(best.Bits), nil
}

// handleGetGenerate implements the getgenerate command.
func handleGetGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.cpuMiner.IsMining(), nil
}

// handleGetHashesPerSec implements the gethashespersec command.
func handleGetHashesPerSec(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	return int64(s.server.cpuMiner.HashesPerSecond()), nil
}

// handleGetHeaders implements the getheaders command.
func handleGetHeaders(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetHeadersCmd)
	blockLocators, err := hcjson.DecodeConcatenatedHashes(c.BlockLocators)
	if err != nil {
		// Already a *hcjson.RPCError
		return nil, err
	}
	var hashStop chainhash.Hash
	if c.HashStop != "" {
		err := chainhash.Decode(&hashStop, c.HashStop)
		if err != nil {
			return nil, rpcInvalidError("Failed to decode "+
				"hashstop: %v", err)
		}
	}
	// Until wire.MsgGetHeaders uses []Hash instead of the []*Hash, this
	// conversion is necessary.  The wire protocol getheaders is (probably)
	// called much more often than this RPC, so server.locateBlocks is
	// optimized for that and this is given the performance penality.
	pBlockLocators := make([]*chainhash.Hash, len(blockLocators))
	for i := range blockLocators {
		pBlockLocators[i] = &blockLocators[i]
	}
	blockHashes, err := s.server.locateBlocks(pBlockLocators, &hashStop)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code: hcjson.ErrRPCDatabase,
			Message: "Failed to fetch hashes of block " +
				"headers: " + err.Error(),
		}
	}
	blockHeaders, err := fetchHeaders(s.server.db, blockHashes)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code: hcjson.ErrRPCDatabase,
			Message: "Failed to fetch headers of located blocks: " +
				err.Error(),
		}
	}

	hexBlockHeaders := make([]string, len(blockHeaders))
	var buf bytes.Buffer
	buf.Grow(wire.MaxBlockHeaderPayload)
	for i, h := range blockHeaders {
		err := h.Serialize(&buf)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Failed to serialize block header")
		}
		hexBlockHeaders[i] = hex.EncodeToString(buf.Bytes())
		buf.Reset()
	}
	return &hcjson.GetHeadersResult{Headers: hexBlockHeaders}, nil
}

// handleGetInfo implements the getinfo command. We only return the fields
// that are not related to wallet functionality.
func handleGetInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()
	ret := &hcjson.InfoChainResult{
		Version: int32(1000000*appMajor + 10000*appMinor +
			100*appPatch),
		ProtocolVersion: int32(maxProtocolVersion),
		Blocks:          best.Height,
		TimeOffset:      int64(s.server.timeSource.Offset().Seconds()),
		Connections:     s.server.ConnectedCount(),
		Proxy:           cfg.Proxy,
		Difficulty:      getDifficultyRatio(best.Bits),
		TestNet:         cfg.TestNet,
		RelayFee:        cfg.minRelayTxFee.ToCoin(),
	}

	return ret, nil
}

// handleGetMempoolInfo implements the getmempoolinfo command.
func handleGetMempoolInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	mempoolTxns := s.server.txMemPool.TxDescs()

	var numBytes int64
	for _, txD := range mempoolTxns {
		numBytes += int64(txD.Tx.MsgTx().SerializeSize())
	}

	ret := &hcjson.GetMempoolInfoResult{
		Size:  int64(len(mempoolTxns)),
		Bytes: numBytes,
	}

	return ret, nil
}

// handleGetMiningInfo implements the getmininginfo command. We only return the
// fields that are not related to wallet functionality.
func handleGetMiningInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// Create a default getnetworkhashps command to use defaults and make
	// use of the existing getnetworkhashps handler.
	gnhpsCmd := hcjson.NewGetNetworkHashPSCmd(nil, nil)
	networkHashesPerSecIface, err := handleGetNetworkHashPS(s, gnhpsCmd,
		closeChan)
	if err != nil {
		return nil, err
	}
	networkHashesPerSec, ok := networkHashesPerSecIface.(int64)
	if !ok {
		return nil, rpcInternalError("invalid network hashes per sec",
			fmt.Sprintf("Invalid type: %q",
				networkHashesPerSecIface))
	}

	best := s.chain.BestSnapshot()
	nextStakeDiff, err := s.chain.CalcNextRequiredStakeDifficulty()
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not calculate next stake difficulty")
	}

	result := hcjson.GetMiningInfoResult{
		Blocks:           best.Height,
		CurrentBlockSize: best.BlockSize,
		CurrentBlockTx:   best.NumTxns,
		Difficulty:       getDifficultyRatio(best.Bits),
		StakeDifficulty:  nextStakeDiff,
		Generate:         s.server.cpuMiner.IsMining(),
		GenProcLimit:     s.server.cpuMiner.NumWorkers(),
		HashesPerSec:     int64(s.server.cpuMiner.HashesPerSecond()),
		NetworkHashPS:    networkHashesPerSec,
		PooledTx:         uint64(s.server.txMemPool.Count()),
		TestNet:          cfg.TestNet,
	}
	return &result, nil
}

// handleGetNetTotals implements the getnettotals command.
func handleGetNetTotals(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	totalBytesRecv, totalBytesSent := s.server.NetTotals()
	reply := &hcjson.GetNetTotalsResult{
		TotalBytesRecv: totalBytesRecv,
		TotalBytesSent: totalBytesSent,
		TimeMillis:     time.Now().UTC().UnixNano() / int64(time.Millisecond),
	}
	return reply, nil
}

// handleGetNetworkHashPS implements the getnetworkhashps command.
func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// Note: All valid error return paths should return an int64.  Literal
	// zeros are inferred as int, and won't coerce to int64 because the
	// return value is an interface{}.

	c := cmd.(*hcjson.GetNetworkHashPSCmd)

	// When the passed height is too high or zero, just return 0 now since
	// we can't reasonably calculate the number of network hashes per
	// second from invalid values.  When it's negative, use the current
	// best block height.
	best := s.chain.BestSnapshot()
	endHeight := int64(-1)
	if c.Height != nil {
		endHeight = int64(*c.Height)
	}
	if endHeight > best.Height || endHeight == 0 {
		return int64(0), nil
	}
	if endHeight < 0 {
		endHeight = best.Height
	}

	// Calculate the number of blocks per retarget interval based on the
	// chain parameters.
	blocksPerRetarget := int64(s.server.chainParams.TargetTimespan /
		s.server.chainParams.TargetTimePerBlock)

	// Calculate the starting block height based on the passed number of
	// blocks.  When the passed value is negative, use the last block the
	// difficulty changed as the starting height.  Also make sure the
	// starting height is not before the beginning of the chain.

	numBlocks := int64(120)
	if c.Blocks != nil {
		numBlocks = int64(*c.Blocks)
	}

	var startHeight int64
	if numBlocks <= 0 {
		startHeight = endHeight - ((endHeight % blocksPerRetarget) + 1)
	} else {
		startHeight = endHeight - numBlocks
	}
	if startHeight < 0 {
		startHeight = 0
	}
	rpcsLog.Debugf("Calculating network hashes per second from %d to %d",
		startHeight, endHeight)

	// Find the min and max block timestamps as well as calculate the total
	// amount of work that happened between the start and end blocks.
	var minTimestamp, maxTimestamp time.Time
	totalWork := big.NewInt(0)
	for curHeight := startHeight; curHeight <= endHeight; curHeight++ {
		hash, err := s.chain.BlockHashByHeight(curHeight)
		if err != nil {
			context := "Failed to fetch block hash"
			return nil, rpcInternalError(err.Error(), context)
		}

		// Load the raw header bytes.
		var headerBytes []byte
		err = s.server.db.View(func(dbTx database.Tx) error {
			var err error
			headerBytes, err = dbTx.FetchBlockHeader(hash)
			return err
		})
		if err != nil {
			context := "Failed to fetch block header"
			return nil, rpcInternalError(err.Error(), context)
		}

		// Deserialize the header.
		var header wire.BlockHeader
		err = header.Deserialize(bytes.NewReader(headerBytes))
		if err != nil {
			context := "Failed to deserialize block header"
			return nil, rpcInternalError(err.Error(), context)
		}

		if curHeight == startHeight {
			minTimestamp = header.Timestamp
			maxTimestamp = minTimestamp
		} else {
			totalWork.Add(totalWork, blockchain.CalcWork(header.Bits))

			if minTimestamp.After(header.Timestamp) {
				minTimestamp = header.Timestamp
			}
			if maxTimestamp.Before(header.Timestamp) {
				maxTimestamp = header.Timestamp
			}
		}
	}

	// Calculate the difference in seconds between the min and max block
	// timestamps and avoid division by zero in the case where there is no
	// time difference.
	timeDiff := int64(maxTimestamp.Sub(minTimestamp) / time.Second)
	if timeDiff == 0 {
		return int64(0), nil
	}

	hashesPerSec := new(big.Int).Div(totalWork, big.NewInt(timeDiff))
	return hashesPerSec.Int64(), nil
}

// handleGetPeerInfo implements the getpeerinfo command.
func handleGetPeerInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	peers := s.server.Peers()
	syncPeer := s.server.blockManager.SyncPeer()
	infos := make([]*hcjson.GetPeerInfoResult, 0, len(peers))
	for _, p := range peers {
		statsSnap := p.StatsSnapshot()
		info := &hcjson.GetPeerInfoResult{
			ID:             statsSnap.ID,
			Addr:           statsSnap.Addr,
			Services:       fmt.Sprintf("%08d", uint64(statsSnap.Services)),
			LastSend:       statsSnap.LastSend.Unix(),
			LastRecv:       statsSnap.LastRecv.Unix(),
			BytesSent:      statsSnap.BytesSent,
			BytesRecv:      statsSnap.BytesRecv,
			ConnTime:       statsSnap.ConnTime.Unix(),
			PingTime:       float64(statsSnap.LastPingMicros),
			TimeOffset:     statsSnap.TimeOffset,
			Version:        statsSnap.Version,
			SubVer:         statsSnap.UserAgent,
			Inbound:        statsSnap.Inbound,
			StartingHeight: statsSnap.StartingHeight,
			CurrentHeight:  statsSnap.LastBlock,
			BanScore:       int32(p.banScore.Int()),
			SyncNode:       p == syncPeer,
		}
		if p.LastPingNonce() != 0 {
			wait := float64(time.Since(statsSnap.LastPingTime).Nanoseconds())
			// We actually want microseconds.
			info.PingWait = wait / 1000
		}
		infos = append(infos, info)
	}
	return infos, nil
}

// handleGetRawMempool implements the getrawmempool command.
func handleGetRawMempool(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetRawMempoolCmd)

	// Choose the type to filter the results by based on the provided param.
	// A filter type of nil means no filtering.
	var filterType *stake.TxType
	if c.TxType != nil {
		switch hcjson.GetRawMempoolTxTypeCmd(*c.TxType) {
		case hcjson.GRMRegular:
			filterType = new(stake.TxType)
			*filterType = stake.TxTypeRegular
		case hcjson.GRMTickets:
			filterType = new(stake.TxType)
			*filterType = stake.TxTypeSStx
		case hcjson.GRMVotes:
			filterType = new(stake.TxType)
			*filterType = stake.TxTypeSSGen
		case hcjson.GRMRevocations:
			filterType = new(stake.TxType)
			*filterType = stake.TxTypeSSRtx
		case hcjson.GRMAll:
			// Nothing to do
		default:
			return nil, rpcInvalidError("Invalid transaction "+
				"type: %T", *c.TxType)
		}
	}

	// Return verbose results if requested.
	mp := s.server.txMemPool
	if c.Verbose != nil && *c.Verbose {
		return mp.RawMempoolVerbose(filterType), nil
	}

	// The response is simply an array of the transaction hashes if the
	// verbose flag is not set.
	descs := mp.TxDescs()
	hashStrings := make([]string, 0, len(descs))
	for i := range descs {
		if filterType != nil && descs[i].Type != *filterType {
			continue
		}
		hashStrings = append(hashStrings, descs[i].Tx.Hash().String())
	}
	return hashStrings, nil
}

// handleGetRawTransaction implements the getrawtransaction command.
func handleGetRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetRawTransactionCmd)

	// Convert the provided transaction hash hex to a Hash.
	txHash, err := chainhash.NewHashFromStr(c.Txid)
	if err != nil {
		return nil, rpcDecodeHexError(c.Txid)
	}

	verbose := false
	if c.Verbose != nil {
		verbose = *c.Verbose != 0
	}

	// Try to fetch the transaction from the memory pool and if that fails,
	// try the block database.
	var mtx *wire.MsgTx
	var blkHash *chainhash.Hash
	var blkHeight int64
	tx, err := s.server.txMemPool.FetchTransaction(txHash, true)
	if err != nil {
		txIndex := s.server.txIndex
		if txIndex == nil {
			return nil, rpcInternalError("The transaction index "+
				"must be enabled to query the blockchain "+
				"(specify --txindex)", "Configuration")
		}

		// Look up the location of the transaction.
		blockRegion, err := txIndex.TxBlockRegion(*txHash)
		if err != nil {
			context := "Failed to retrieve transaction location"
			return nil, rpcInternalError(err.Error(), context)
		}
		if blockRegion == nil {
			return nil, rpcNoTxInfoError(txHash)
		}

		// Load the raw transaction bytes from the database.
		var txBytes []byte
		err = s.server.db.View(func(dbTx database.Tx) error {
			var err error
			txBytes, err = dbTx.FetchBlockRegion(blockRegion)
			return err
		})
		if err != nil {
			return nil, rpcNoTxInfoError(txHash)
		}

		// When the verbose flag isn't set, simply return the serialized
		// transaction as a hex-encoded string.  This is done here to
		// avoid deserializing it only to reserialize it again later.
		if !verbose {
			return hex.EncodeToString(txBytes), nil
		}

		// Grab the block height.
		blkHash = blockRegion.Hash
		blkHeight, err = s.chain.BlockHeightByHash(blkHash)
		if err != nil {
			context := "Failed to retrieve block height"
			return nil, rpcInternalError(err.Error(), context)
		}

		// Deserialize the transaction
		var msgTx wire.MsgTx
		err = msgTx.Deserialize(bytes.NewReader(txBytes))
		if err != nil {
			context := "Failed to deserialize transaction"
			return nil, rpcInternalError(err.Error(), context)
		}
		mtx = &msgTx
	} else {
		// When the verbose flag isn't set, simply return the
		// network-serialized transaction as a hex-encoded string.
		if !verbose {
			// Note that this is intentionally not directly
			// returning because the first return value is a
			// string and it would result in returning an empty
			// string to the client instead of nothing (nil) in the
			// case of an error.
			mtxHex, err := messageToHex(tx.MsgTx())
			if err != nil {
				return nil, err
			}
			return mtxHex, nil
		}

		mtx = tx.MsgTx()
	}

	// The verbose flag is set, so generate the JSON object and return it.
	var (
		blkHeader     *wire.BlockHeader
		blkHashStr    string
		confirmations int64
	)
	if blkHash != nil {
		// Load the raw header bytes.
		var headerBytes []byte
		err := s.server.db.View(func(dbTx database.Tx) error {
			var err error
			headerBytes, err = dbTx.FetchBlockHeader(blkHash)
			return err
		})
		if err != nil {
			context := "Failed to fetch block header"
			return nil, rpcInternalError(err.Error(), context)
		}

		// Deserialize the header.
		var header wire.BlockHeader
		err = header.Deserialize(bytes.NewReader(headerBytes))
		if err != nil {
			context := "Failed to deserialize block header"
			return nil, rpcInternalError(err.Error(), context)
		}

		blkHeader = &header
		blkHashStr = blkHash.String()
		confirmations = 1 + s.chain.BestSnapshot().Height - blkHeight
	}

	rawTxn, err := createTxRawResult(s.server.chainParams, mtx,
		txHash.String(), 0, blkHeader, blkHashStr, blkHeight,
		confirmations)
	if err != nil {
		return nil, err
	}
	return *rawTxn, nil
}

// handleGetStakeDifficulty implements the getstakedifficulty command.
func handleGetStakeDifficulty(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()
	blockHeader, err := s.chain.HeaderByHeight(best.Height)
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCDifficulty,
			Message: "Error getting stake difficulty: " + err.Error(),
		}
	}
	currentSdiff := hcutil.Amount(blockHeader.SBits)

	nextSdiff, err := s.server.blockManager.CalcNextRequiredStakeDifficulty()
	if err != nil {
		return nil, rpcInternalError("Could not calculate next stake "+
			"difficulty "+err.Error(), "")
	}
	nextSdiffAmount := hcutil.Amount(nextSdiff)

	sDiffResult := &hcjson.GetStakeDifficultyResult{
		CurrentStakeDifficulty: currentSdiff.ToCoin(),
		NextStakeDifficulty:    nextSdiffAmount.ToCoin(),
	}

	return sDiffResult, nil
}

// convertVersionMap translates a map[int]int into a sorted array of
// VersionCount that contains the same information.
func convertVersionMap(m map[int]int) []hcjson.VersionCount {
	sorted := make([]hcjson.VersionCount, 0, len(m))
	order := make([]int, 0, len(m))
	for k := range m {
		order = append(order, k)
	}
	sort.Ints(order)

	for _, v := range order {
		sorted = append(sorted, hcjson.VersionCount{Version: uint32(v),
			Count: uint32(m[v])})
	}

	return sorted
}

// handleGetBlockchainInfo implements the getblockchaininfo command.
func handleGetBlockchainInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	best := s.chain.BestSnapshot()

	// Fetch the current chain work using the the best block hash.
	chainWork, err := s.chain.ChainWork(best.Hash)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Could not fetch chain work.")
	}

	// Estimate the verification progress of the node.
	syncHeight := s.server.blockManager.chainState.newestHeight
	var verifyProgress float64
	if syncHeight > 0 {
		verifyProgress = math.Min(float64(best.Height)/float64(syncHeight), 1.0)
	}

	// Fetch the maximum allowed block size.
	maxBlockSize, err := s.chain.MaxBlockSize()
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not fetch max block size.")
	}

	// Fetch the agendas of the consensus deployments as well as their
	// threshold states and state activation heights.

	//dInfo := make(map[string]hcjson.AgendaInfo)
	//params := s.server.chainParams
	//for version, deployments := range params.Deployments {
	//	for _, agenda := range deployments {
	//		aInfo := hcjson.AgendaInfo{
	//			StartTime:  agenda.StartTime,
	//			ExpireTime: agenda.ExpireTime,
	//		}
	//
	//		state, err := s.chain.NextThresholdState(&best.PrevHash, version,
	//			agenda.Vote.Id)
	//		if err != nil {
	//			return nil, rpcInternalError(err.Error(),
	//				fmt.Sprintf("Could not fetch threshold state "+
	//					"for agenda with id (%v).", agenda.Vote.Id))
	//		}
	//
	//		stateChangedHeight, err := s.chain.StateLastChangedHeight(
	//			&best.Hash, version, agenda.Vote.Id)
	//		if err != nil {
	//			return nil, rpcInternalError(err.Error(),
	//				fmt.Sprintf("Could not fetch state last changed "+
	//					"height for agenda with id (%v).", agenda.Vote.Id))
	//		}
	//
	//		aInfo.Since = stateChangedHeight
	//		aInfo.Status = state.String()
	//		dInfo[agenda.Vote.Id] = aInfo
	//	}
	//}

	// Generate rpc response.
	response := hcjson.GetBlockChainInfoResult{
		Chain:      s.server.chainParams.Name,
		Blocks:     int32(best.Height),
		Headers:    int32(best.Height),
		SyncHeight: syncHeight,
		ChainWork:  fmt.Sprintf("%064x", chainWork),
		//InitialBlockDownload: !s.chain.IsCurrent(),
		VerificationProgress: verifyProgress,
		BestBlockHash:        best.Hash.String(),
		Difficulty:           float64(best.Bits),
		DifficultyRatio:      getDifficultyRatio(best.Bits),
		MaxBlockSize:         maxBlockSize,
		//Deployments:          dInfo,
	}

	return response, nil
}

// handleGetStakeVersionInfo implements the getstakeversioninfo command.
func handleGetStakeVersionInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	count := int32(1)
	c, ok := cmd.(*hcjson.GetStakeVersionInfoCmd)
	if !ok {
		return nil, rpcInvalidError("Invalid type: %T", c)
	}
	if c.Count != nil {
		count = *c.Count
		if count <= 0 {
			return nil, rpcInvalidError("Count must be positive")
		}
	}

	snapshot := s.chain.BestSnapshot()

	interval := s.server.chainParams.StakeVersionInterval
	// Assemble JSON result.
	result := hcjson.GetStakeVersionInfoResult{
		CurrentHeight: snapshot.Height,
		Hash:          snapshot.Hash.String(),
		Intervals:     make([]hcjson.VersionInterval, 0, count),
	}

	startHeight := snapshot.Height
	endHeight := s.chain.CalcWantHeight(interval,
		snapshot.Height) + 1
	hash := snapshot.Hash
	adjust := int32(1) // We are off by one on the initial iteration.
	for i := int32(0); i < count; i++ {
		numBlocks := int32(startHeight - endHeight)
		if numBlocks <= 0 {
			// Just return what we got.
			break
		}
		sv, err := s.chain.GetStakeVersions(hash, numBlocks+adjust)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"handleGetStakeVersionInfo")
		}

		posVersions := make(map[int]int)
		voteVersions := make(map[int]int)
		for _, v := range sv {
			posVersions[int(v.StakeVersion)]++
			for _, vote := range v.Votes {
				voteVersions[int(vote.Version)]++
			}
		}
		versionInterval := hcjson.VersionInterval{
			StartHeight:  endHeight,
			EndHeight:    startHeight,
			PoSVersions:  convertVersionMap(posVersions),
			VoteVersions: convertVersionMap(voteVersions),
		}
		result.Intervals = append(result.Intervals, versionInterval)

		// Adjust interval.
		endHeight -= interval
		startHeight = endHeight + interval
		adjust = 0

		// Get prior block hash.
		hash, err = s.chain.BlockHashByHeight(startHeight - 1)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"handleGetStakeVersionInfo")
		}
	}

	return result, nil
}

// handleGetStakeVersions implements the getstakeversions command.
func handleGetStakeVersions(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetStakeVersionsCmd)

	hash, err := chainhash.NewHashFromStr(c.Hash)
	if err != nil {
		return nil, rpcDecodeHexError(c.Hash)
	}
	if c.Count <= 0 {
		return nil, rpcInvalidError("Invalid parameter, count must " +
			"be > 0")
	}

	sv, err := s.chain.GetStakeVersions(hash, c.Count)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not obtain stake versions")
	}

	result := hcjson.GetStakeVersionsResult{
		StakeVersions: make([]hcjson.StakeVersions, 0, len(sv)),
	}
	for _, v := range sv {
		nsv := hcjson.StakeVersions{
			Hash:         v.Hash.String(),
			Height:       v.Height,
			BlockVersion: v.BlockVersion,
			StakeVersion: v.StakeVersion,
			Votes: make([]hcjson.VersionBits, 0,
				len(v.Votes)),
		}
		for _, vote := range v.Votes {
			nsv.Votes = append(nsv.Votes,
				hcjson.VersionBits{Version: vote.Version,
					Bits: vote.Bits})
		}

		result.StakeVersions = append(result.StakeVersions, nsv)
	}

	return result, nil
}

// handleGetTicketPoolValue implements the getticketpoolvalue command.
func handleGetTicketPoolValue(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	amt, err := s.server.blockManager.TicketPoolValue()
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not obtain ticket pool value")
	}

	return amt.ToCoin(), nil
}

// handleGetVoteInfo implements the getvoteinfo command.
func handleGetVoteInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c, ok := cmd.(*hcjson.GetVoteInfoCmd)
	if !ok {
		return nil, rpcInvalidError("Invalid type: %T", c)
	}

	snapshot := s.chain.BestSnapshot()

	interval := int64(s.server.chainParams.RuleChangeActivationInterval)
	quorum := s.server.chainParams.RuleChangeActivationQuorum
	// Assemble JSON result.
	result := hcjson.GetVoteInfoResult{
		CurrentHeight: snapshot.Height,
		StartHeight: s.chain.CalcWantHeight(interval,
			snapshot.Height) + 1,
		EndHeight: s.chain.CalcWantHeight(interval,
			snapshot.Height) + interval,
		Hash:        snapshot.Hash.String(),
		VoteVersion: c.Version,
		Quorum:      quorum,
	}

	// We don't fail, we try to return the totals for this version.
	var err error
	result.TotalVotes, err = s.chain.CountVoteVersion(c.Version)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not count voter versions")
	}

	vi, err := s.chain.GetVoteInfo(snapshot.Hash, c.Version)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not obtain vote info")
	}

	result.Agendas = make([]hcjson.Agenda, 0, len(vi.Agendas))
	for _, agenda := range vi.Agendas {
		a := hcjson.Agenda{
			Id:          agenda.Vote.Id,
			Description: agenda.Vote.Description,
			Mask:        agenda.Vote.Mask,
			Choices: make([]hcjson.Choice, 0,
				len(agenda.Vote.Choices)),
			StartTime:  agenda.StartTime,
			ExpireTime: agenda.ExpireTime,
		}

		// Handle choices.
		for _, choice := range agenda.Vote.Choices {
			c := hcjson.Choice{
				Id:          choice.Id,
				Description: choice.Description,
				Bits:        choice.Bits,
				IsAbstain:   choice.IsAbstain,
				IsNo:        choice.IsNo,
			}
			a.Choices = append(a.Choices, c)
		}

		// Obtain status of agenda.
		state, err := s.chain.ThresholdState(snapshot.Hash, c.Version,
			agenda.Vote.Id)
		if err != nil {
			return nil, err
		}

		// Save off status.
		a.Status = state.String()

		if state.State != blockchain.ThresholdStarted {
			// Append transformed agenda without progress.
			result.Agendas = append(result.Agendas, a)
			continue
		}

		counts, err := s.chain.GetVoteCounts(c.Version, agenda.Vote.Id)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not obtain vote count")
		}

		// Calculate quorum.
		qmin := quorum
		totalNonAbstain := counts.Total - counts.TotalAbstain
		if totalNonAbstain < quorum {
			qmin = totalNonAbstain
		}
		a.QuorumProgress = float64(qmin) / float64(quorum)

		// Calcualte choice progress.
		for k := range a.Choices {
			a.Choices[k].Count = counts.VoteChoices[k]
			a.Choices[k].Progress = float64(counts.VoteChoices[k]) /
				float64(counts.Total)
		}

		// Append transformed agenda.
		result.Agendas = append(result.Agendas, a)
	}

	return result, nil
}

// bigToLEUint256 returns the passed big integer as an unsigned 256-bit integer
// encoded as little-endian bytes.  Numbers which are larger than the max
// unsigned 256-bit integer are truncated.
func bigToLEUint256(n *big.Int) [uint256Size]byte {
	// Pad or truncate the big-endian big int to correct number of bytes.
	nBytes := n.Bytes()
	nlen := len(nBytes)
	pad := 0
	start := 0
	if nlen <= uint256Size {
		pad = uint256Size - nlen
	} else {
		start = nlen - uint256Size
	}
	var buf [uint256Size]byte
	copy(buf[pad:], nBytes[start:])

	// Reverse the bytes to little endian and return them.
	for i := 0; i < uint256Size/2; i++ {
		buf[i], buf[uint256Size-1-i] = buf[uint256Size-1-i], buf[i]
	}
	return buf
}

// handleGetTxOut handles gettxout commands.
func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.GetTxOutCmd)

	// Convert the provided transaction hash hex to a Hash.
	txHash, err := chainhash.NewHashFromStr(c.Txid)
	if err != nil {
		return nil, rpcDecodeHexError(c.Txid)
	}

	// If requested and the tx is available in the mempool try to fetch it
	// from there, otherwise attempt to fetch from the block database.
	var bestBlockHash string
	var confirmations int64
	var txVersion uint16
	var value int64
	var scriptVersion uint16
	var pkScript []byte
	var isCoinbase bool
	includeMempool := true
	if c.IncludeMempool != nil {
		includeMempool = *c.IncludeMempool
	}
	var txFromMempool *hcutil.Tx
	if includeMempool {
		txFromMempool, _ = s.server.txMemPool.FetchTransaction(txHash,
			true)
	}
	if txFromMempool != nil {
		mtx := txFromMempool.MsgTx()
		if c.Vout > uint32(len(mtx.TxOut)-1) {
			return nil, &hcjson.RPCError{
				Code: hcjson.ErrRPCInvalidTxVout,
				Message: "Ouput index number (vout) does not " +
					"exist for transaction.",
			}
		}

		txOut := mtx.TxOut[c.Vout]
		if txOut == nil {
			errStr := fmt.Sprintf("Output index: %d for txid: %s "+
				"does not exist", c.Vout, txHash)
			return nil, rpcInternalError(errStr, "")
		}

		best := s.chain.BestSnapshot()
		bestBlockHash = best.Hash.String()
		confirmations = 0
		txVersion = mtx.Version
		value = txOut.Value
		scriptVersion = txOut.Version
		pkScript = txOut.PkScript
		isCoinbase = blockchain.IsCoinBaseTx(mtx)
	} else {
		entry, err := s.chain.FetchUtxoEntry(txHash)
		if err != nil {
			return nil, rpcNoTxInfoError(txHash)
		}

		// To match the behavior of the reference client, return nil
		// (JSON null) if the transaction output is spent by another
		// transaction already in the main chain.  Mined transactions
		// that are spent by a mempool transaction are not affected by
		// this.
		if entry == nil || entry.IsOutputSpent(c.Vout) {
			return nil, nil
		}

		best := s.chain.BestSnapshot()
		bestBlockHash = best.Hash.String()
		confirmations = 1 + best.Height - entry.BlockHeight()
		txVersion = entry.TxVersion()
		value = entry.AmountByIndex(c.Vout)
		scriptVersion = entry.ScriptVersionByIndex(c.Vout)
		pkScript = entry.PkScriptByIndex(c.Vout)
		isCoinbase = entry.IsCoinBase()
	}

	// Disassemble script into single line printable format.  The
	// disassembled string will contain [error] inline if the script
	// doesn't fully parse, so ignore the error here.
	script := pkScript
	disbuf, _ := txscript.DisasmString(script)

	// Get further info about the script.  Ignore the error here since an
	// error means the script couldn't parse and there is no additional
	// information about it anyways.
	scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(scriptVersion,
		script, s.server.chainParams)
	addresses := make([]string, len(addrs))
	for i, addr := range addrs {
		addresses[i] = addr.EncodeAddress()
	}

	txOutReply := &hcjson.GetTxOutResult{
		BestBlock:     bestBlockHash,
		Confirmations: confirmations,
		Value:         hcutil.Amount(value).ToUnit(hcutil.AmountCoin),
		Version:       int32(txVersion),
		ScriptPubKey: hcjson.ScriptPubKeyResult{
			Asm:       disbuf,
			Hex:       hex.EncodeToString(pkScript),
			ReqSigs:   int32(reqSigs),
			Type:      scriptClass.String(),
			Addresses: addresses,
		},
		Coinbase: isCoinbase,
	}
	return txOutReply, nil
}

// pruneOldBlockTemplates prunes all old block templates from the templatePool
// map. Must be called with the RPC workstate locked to avoid races to the map.
func pruneOldBlockTemplates(s *rpcServer, bestHeight int64) {
	pool := s.templatePool
	for rootHash, blkData := range pool {
		height := int64(blkData.msgBlock.Header.Height)
		if height < bestHeight-getworkExpirationDiff {
			delete(pool, rootHash)
		}
	}
}

// handleGetWorkRequest is a helper for handleGetWork which deals with
// generating and returning work to the caller.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
	state := s.workState

	// Generate a new block template when the current best block has
	// changed or the transactions in the memory pool have been updated and
	// it has been at least one minute since the last template was
	// generated.
	lastTxUpdate := s.server.txMemPool.LastUpdated()
	latestHash, latestHeight := s.server.blockManager.chainState.Best()
	msgBlock := state.msgBlock

	// The current code pulls down a new template every second, however
	// with a large mempool this will be pretty excruciating sometimes. It
	// should examine whether or not a new template needs to be created
	// based on the votes present every second or so, and then, if needed,
	// generate a new block template. TODO cj
	if msgBlock == nil || state.prevHash == nil ||
		!state.prevHash.IsEqual(latestHash) ||
		(state.lastTxUpdate != lastTxUpdate &&
			time.Now().After(state.lastGenerated.Add(time.Second))) {
		// Reset the extra nonce and clear all expired cached template
		// variations if the best block changed.
		if state.prevHash != nil && !state.prevHash.IsEqual(latestHash) {
			state.extraNonce = 0
			pruneOldBlockTemplates(s, latestHeight)
		}

		// Reset the previous best hash the block template was
		// generated against so any errors below cause the next
		// invocation to try again.
		state.prevHash = nil

		// Choose a payment address at random.
		payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]

		template, err := NewBlockTemplate(s.policy, s.server, payToAddr)
		if err != nil {
			context := "Failed to create new block template"
			return nil, rpcInternalError(err.Error(), context)
		}
		if template == nil {
			// This happens if the template is returned nil because
			// there are not enough voters on HEAD and there is
			// currently an unsuitable parent cached template to
			// try building off of.
			context := "Failed to create new block template: not " +
				"enough voters and failed to find a suitable " +
				"parent template to build from"
			return nil, rpcInternalError("internal error", context)
		}
		templateCopy := deepCopyBlockTemplate(template)
		msgBlock = templateCopy.Block

		// Update work state to ensure another block template isn't
		// generated until needed.
		state.msgBlock = msgBlock
		state.lastGenerated = time.Now()
		state.lastTxUpdate = lastTxUpdate
		state.prevHash = latestHash

		rpcsLog.Debugf("Generated block template (timestamp %v, extra "+
			"nonce %d, target %064x, merkle root %s)",
			msgBlock.Header.Timestamp, state.extraNonce,
			blockchain.CompactToBig(msgBlock.Header.Bits),
			msgBlock.Header.MerkleRoot)
	} else {
		// At this point, there is a saved block template and a new
		// request for work was made, but either the available
		// transactions haven't change or it hasn't been long enough to
		// trigger a new block template to be generated.  So, update the
		// existing block template and track the variations so each
		// variation can be regenerated if a caller finds an answer and
		// makes a submission against it.
		templateCopy := deepCopyBlockTemplate(&BlockTemplate{
			Block: msgBlock,
		})
		msgBlock = templateCopy.Block

		// Update the time of the block template to the current time
		// while accounting for the median time of the past several
		// blocks per the chain consensus rules.
		UpdateBlockTime(msgBlock, s.server.blockManager)

		if templateCopy.Height > 1 {
			// Increment the extra nonce and update the block template
			// with the new value by regenerating the coinbase script and
			// setting the merkle root to the new value.
			ens := getCoinbaseExtranonces(msgBlock)
			state.extraNonce++
			ens[0]++
			err := UpdateExtraNonce(msgBlock, latestHeight+1, ens)
			if err != nil {
				errStr := fmt.Sprintf("Failed to update extra nonce: "+
					"%v", err)
				return nil, rpcInternalError(errStr, "")
			}
		}

		rpcsLog.Debugf("Updated block template (timestamp %v, extra "+
			"nonce %d, target %064x, merkle root %s)",
			msgBlock.Header.Timestamp,
			state.extraNonce,
			blockchain.CompactToBig(msgBlock.Header.Bits),
			msgBlock.Header.MerkleRoot)
	}

	// In order to efficiently store the variations of block templates that
	// have been provided to callers, save a pointer to the block as well
	// as the modified signature script keyed by the merkle root.  This
	// information, along with the data that is included in a work
	// submission, is used to rebuild the block before checking the
	// submitted solution.
	coinbaseTx := msgBlock.Transactions[0]

	// Create the new merkleRootPair key which is MerkleRoot + StakeRoot
	var merkleRootPair [merkleRootPairSize]byte
	copy(merkleRootPair[:chainhash.HashSize], msgBlock.Header.MerkleRoot[:])
	copy(merkleRootPair[chainhash.HashSize:], msgBlock.Header.StakeRoot[:])

	if msgBlock.Header.Height > 1 {
		s.templatePool[merkleRootPair] = &workStateBlockInfo{
			msgBlock: msgBlock,
			pkScript: coinbaseTx.TxOut[1].PkScript,
		}
	} else {
		s.templatePool[merkleRootPair] = &workStateBlockInfo{
			msgBlock: msgBlock,
		}
	}

	// Serialize the block header into a buffer large enough to hold the
	// the block header and the internal blake256 padding that is added and
	// retuned as part of the data below.  For reference:
	// data[116] --> nBits
	// data[136] --> Timestamp
	// data[140] --> nonce
	data := make([]byte, 0, getworkDataLen)
	buf := bytes.NewBuffer(data)
	err := msgBlock.Header.Serialize(buf)
	if err != nil {
		errStr := fmt.Sprintf("Failed to serialize data: %v", err)
		return nil, rpcInternalError(errStr, "")
	}

	// Expand the data slice to include the full data buffer and apply the
	// internal blake256 padding.  This makes the data ready for callers to
	// make use of only the final chunk along with the midstate for the
	// rest.
	data = data[:getworkDataLen]
	copy(data[wire.MaxBlockHeaderPayload:], blake256Pad)

	// The final result reverses each of the fields to little endian.  In
	// particular, the data, hash1, and midstate fields are treated as
	// arrays of uint32s (per the internal sha256 hashing state) which are
	// in big endian, and thus each 4 bytes is byte swapped.  The target is
	// also in big endian, but it is treated as a uint256 and byte swapped
	// to little endian accordingly.
	//
	// The fact the fields are reversed in this way is rather odd and likey
	// an artifact of some legacy internal state in the reference
	// implementation, but it is required for compatibility.
	target := bigToLEUint256(blockchain.CompactToBig(msgBlock.Header.Bits))
	reply := &hcjson.GetWorkResult{
		Data:   hex.EncodeToString(data),
		Target: hex.EncodeToString(target[:]),
	}
	return reply, nil
}

// handleGetWorkSubmission is a helper for handleGetWork which deals with
// the calling submitting work to be verified and processed.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkSubmission(s *rpcServer, hexData string) (interface{}, error) {
	// Ensure the provided data is sane.
	if len(hexData)%2 != 0 {
		hexData = "0" + hexData
	}
	data, err := hex.DecodeString(hexData)
	if err != nil {
		return false, rpcDecodeHexError(hexData)
	}
	if len(data) != getworkDataLen {
		return nil, rpcInvalidError("Argument must be %d bytes (not "+
			"%d)", getworkDataLen, len(data))
	}

	// Deserialize the block header from the data.
	var submittedHeader wire.BlockHeader
	bhBuf := bytes.NewReader(data[0:wire.MaxBlockHeaderPayload])
	err = submittedHeader.Deserialize(bhBuf)
	if err != nil {
		return false, rpcInvalidError("Invalid block header: %v", err)
	}

	// Create the new merkleRootPair key which is MerkleRoot + StakeRoot
	var merkleRootPair [merkleRootPairSize]byte
	copy(merkleRootPair[:chainhash.HashSize], submittedHeader.MerkleRoot[:])
	copy(merkleRootPair[chainhash.HashSize:], submittedHeader.StakeRoot[:])

	// Look up the full block for the provided data based on the merkle
	// root.  Return false to indicate the solve failed if it's not
	// available.
	blockInfo, ok := s.templatePool[merkleRootPair]
	if !ok {
		rpcsLog.Errorf("Block submitted via getwork has no matching "+
			"template for merkle root %s",
			submittedHeader.MerkleRoot)
		return false, nil
	}

	// Reconstruct the block using the submitted header stored block info.
	// The MsgBlock is copied here because it could be accessed
	// outside of the GW workstate mutexes once it gets submitted to the
	// blockchain.
	tempBlock := hcutil.NewBlockDeepCopy(blockInfo.msgBlock)
	msgBlock := tempBlock.MsgBlock()
	msgBlock.Header = submittedHeader
	if msgBlock.Header.Height > 1 {
		pkScriptCopy := make([]byte, len(blockInfo.pkScript))
		copy(pkScriptCopy, blockInfo.pkScript)
		msgBlock.Transactions[0].TxOut[1].PkScript = blockInfo.pkScript
		merkles := blockchain.BuildMerkleTreeStore(tempBlock.Transactions())
		msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
	}

	// The real block to submit, with a proper nonce and extraNonce.
	block := hcutil.NewBlockDeepCopyCoinbase(msgBlock)

	// Ensure the submitted block hash is less than the target difficulty.
	err = blockchain.CheckProofOfWork(block, activeNetParams.PowLimit)
	if err != nil {
		// Anything other than a rule violation is an unexpected error,
		// so return that error as an internal error.
		if _, ok := err.(blockchain.RuleError); !ok {
			return false, rpcInternalError("Unexpected error "+
				"while checking proof of work: "+err.Error(),
				"")
		}

		rpcsLog.Errorf("Block submitted via getwork does not meet "+
			"the required proof of work: %v", err)
		return false, nil
	}

	// Process this block using the same rules as blocks coming from other
	// nodes.  This will in turn relay it to the network like normal.
	isOrphan, err := s.server.blockManager.ProcessBlock(block,
		blockchain.BFNone)
	if err != nil || isOrphan {
		// Anything other than a rule violation is an unexpected error,
		// so return that error as an internal error.
		if _, ok := err.(blockchain.RuleError); !ok {
			return false, rpcInternalError("Unexpected error "+
				"while processing block: "+err.Error(), "")
		}

		rpcsLog.Infof("Block submitted via getwork rejected: %v", err)
		return false, nil
	}

	// The block was accepted.
	rpcsLog.Infof("Block submitted via getwork accepted: %s", block.Hash())
	return true, nil
}

// handleGetWork implements the getwork command.
func handleGetWork(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	if s.server.cpuMiner.IsMining() {
		return nil, rpcMiscError("getwork polling is disallowed " +
			"while CPU mining is enabled. Please disable CPU " +
			"mining and try again.")
	}

	// Respond with an error if there are no addresses to pay the created
	// blocks to.
	if len(cfg.miningAddrs) == 0 {
		return nil, rpcInternalError("No payment addresses specified "+
			"via --miningaddr", "Configuration")
	}

	// Return an error if there are no peers connected since there is no
	// way to relay a found block or receive transactions to work on.
	// However, allow this state when running in the regression test or
	// simulation test mode.
	if !cfg.SimNet && s.server.ConnectedCount() == 0 {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCClientNotConnected,
			Message: "Hcd is not connected",
		}
	}

	// No point in generating or accepting work before the chain is synced.
	_, currentHeight := s.server.blockManager.chainState.Best()
	if currentHeight != 0 && !s.server.blockManager.IsCurrent() {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCClientInInitialDownload,
			Message: "Hcd is downloading blocks...",
		}
	}

	c := cmd.(*hcjson.GetWorkCmd)

	// Protect concurrent access from multiple RPC invocations for work
	// requests and submission.
	s.workState.Lock()
	defer s.workState.Unlock()

	// When the caller provides data, it is a submission of a supposedly
	// solved block that needs to be checked and submitted to the network
	// if valid.
	if c.Data != nil && *c.Data != "" {
		return handleGetWorkSubmission(s, *c.Data)
	}

	// No data was provided, so the caller is requesting work.
	return handleGetWorkRequest(s)
}

// handleHelp implements the help command.
func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.HelpCmd)

	// Provide a usage overview of all commands when no specific command
	// was specified.
	var command string
	if c.Command != nil {
		command = *c.Command
	}
	if command == "" {
		usage, err := s.helpCacher.rpcUsage(false)
		if err != nil {
			context := "Failed to generate RPC usage"
			return nil, rpcInternalError(err.Error(), context)
		}
		return usage, nil
	}

	// Check that the command asked for is supported and implemented.  Only
	// search the main list of handlers since help should not be provided
	// for commands that are unimplemented or related to wallet
	// functionality.
	if _, ok := rpcHandlers[command]; !ok {
		return nil, rpcInvalidError("Unknown command: %v", command)
	}

	// Get the help for the command.
	help, err := s.helpCacher.rpcMethodHelp(command)
	if err != nil {
		context := "Failed to generate help"
		return nil, rpcInternalError(err.Error(), context)
	}
	return help, nil
}

// handleLiveTickets implements the livetickets command.
func handleLiveTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	lt, err := s.server.blockManager.chain.LiveTickets()
	if err != nil {
		return nil, rpcInternalError("Could not get live tickets "+
			err.Error(), "")
	}

	ltString := make([]string, len(lt))
	for i := range lt {
		ltString[i] = lt[i].String()
	}

	return hcjson.LiveTicketsResult{Tickets: ltString}, nil
}

// handleMissedTickets implements the missedtickets command.
func handleMissedTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	mt, err := s.server.blockManager.chain.MissedTickets()
	if err != nil {
		return nil, rpcInternalError("Could not get missed tickets "+
			err.Error(), "")
	}

	mtString := make([]string, len(mt))
	for i, hash := range mt {
		mtString[i] = hash.String()
	}

	return hcjson.MissedTicketsResult{Tickets: mtString}, nil
}

// handlePing implements the ping command.
func handlePing(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// Ask server to ping \o_
	nonce, err := wire.RandomUint64()
	if err != nil {
		return nil, rpcInternalError("Not sending ping - failed to "+
			"generate nonce: "+err.Error(), "")
	}
	s.server.BroadcastMessage(wire.NewMsgPing(nonce))

	return nil, nil
}

// handleRebroadcastMissed implements the rebroadcastmissed command.
func handleRebroadcastMissed(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	hash, height := s.server.blockManager.chainState.Best()
	mt, err := s.server.blockManager.chain.MissedTickets()
	if err != nil {
		return nil, rpcInternalError("Could not get missed tickets "+
			err.Error(), "")
	}

	stakeDiff, err := s.server.blockManager.CalcNextRequiredStakeDifficulty()
	if err != nil {
		return nil, rpcInternalError("Could not calculate next stake "+
			"difficulty "+err.Error(), "")
	}

	missedTicketsNtfn := &blockchain.TicketNotificationsData{
		Hash:            *hash,
		Height:          height,
		StakeDifficulty: stakeDiff,
		TicketsSpent:    []chainhash.Hash{},
		TicketsMissed:   mt,
		TicketsNew:      []chainhash.Hash{},
	}

	s.ntfnMgr.NotifySpentAndMissedTickets(missedTicketsNtfn)

	return nil, nil
}

// handleRebroadcastWinners implements the rebroadcastwinners command.
func handleRebroadcastWinners(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	hash, height := s.server.blockManager.chainState.Best()
	blocks, err := s.server.blockManager.TipGeneration()
	if err != nil {
		return nil, rpcInternalError("Could not get generation "+
			err.Error(), "")
	}

	for i := range blocks {
		winningTickets, _, _, err :=
			s.server.blockManager.chain.LotteryDataForBlock(&blocks[i])
		if err != nil {
			return nil, rpcInternalError("Lottery data for block "+
				"failed: "+err.Error(), "")
		}
		ntfnData := &WinningTicketsNtfnData{
			BlockHash:   *hash,
			BlockHeight: height,
			Tickets:     winningTickets,
		}

		s.ntfnMgr.NotifyWinningTickets(ntfnData)
	}

	return nil, nil
}

// retrievedTx represents a transaction that was either loaded from the
// transaction memory pool or from the database.  When a transaction is loaded
// from the database, it is loaded with the raw serialized bytes while the
// mempool has the fully deserialized structure.  This structure therefore will
// have one of the two fields set depending on where is was retrieved from.
// This is mainly done for efficiency to avoid extra serialization steps when
// possible.
type retrievedTx struct {
	txBytes []byte
	blkHash *chainhash.Hash // Only set when transaction is in a block.
	tx      *hcutil.Tx
}

// fetchInputTxos fetches the outpoints from all transactions referenced by the
// inputs to the passed transaction by checking the transaction mempool first
// then the transaction index for those already mined into blocks.
func fetchInputTxos(s *rpcServer, tx *wire.MsgTx) (map[wire.OutPoint]wire.TxOut, error) {
	mp := s.server.txMemPool
	originOutputs := make(map[wire.OutPoint]wire.TxOut)
	voteTx, _ := stake.IsSSGen(tx)
	for txInIndex, txIn := range tx.TxIn {
		// vote tx have null input for vin[0],
		// skip since it resolvces to an invalid transaction
		if voteTx && txInIndex == 0 {
			continue
		}
		// Attempt to fetch and use the referenced transaction from the
		// memory pool.
		origin := &txIn.PreviousOutPoint
		originTx, err := mp.FetchTransaction(&origin.Hash, true)
		if err == nil {
			txOuts := originTx.MsgTx().TxOut
			if origin.Index >= uint32(len(txOuts)) {
				errStr := fmt.Sprintf("unable to find output "+
					"%v referenced from transaction %s:%d",
					origin, tx.TxHash(), txInIndex)
				return nil, rpcInternalError(errStr, "")
			}

			originOutputs[*origin] = *txOuts[origin.Index]
			continue
		}

		// Look up the location of the transaction.
		blockRegion, err := s.server.txIndex.TxBlockRegion(origin.Hash)
		if err != nil {
			context := "Failed to retrieve transaction location"
			return nil, rpcInternalError(err.Error(), context)
		}
		if blockRegion == nil {
			return nil, rpcNoTxInfoError(&origin.Hash)
		}

		// Load the raw transaction bytes from the database.
		var txBytes []byte
		err = s.server.db.View(func(dbTx database.Tx) error {
			var err error
			txBytes, err = dbTx.FetchBlockRegion(blockRegion)
			return err
		})
		if err != nil {
			return nil, rpcNoTxInfoError(&origin.Hash)
		}

		// Deserialize the transaction
		var msgTx wire.MsgTx
		err = msgTx.Deserialize(bytes.NewReader(txBytes))
		if err != nil {
			context := "Failed to deserialize transaction"
			return nil, rpcInternalError(err.Error(), context)
		}

		// Add the referenced output to the map.
		if origin.Index >= uint32(len(msgTx.TxOut)) {
			errStr := fmt.Sprintf("unable to find output %v "+
				"referenced from transaction %s:%d", origin,
				tx.TxHash(), txInIndex)
			return nil, rpcInternalError(errStr, "")
		}
		originOutputs[*origin] = *msgTx.TxOut[origin.Index]
	}

	return originOutputs, nil
}

// createVinListPrevOut returns a slice of JSON objects for the inputs of the
// passed transaction.
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra bool, filterAddrMap map[string]struct{}) ([]hcjson.VinPrevOut, error) {
	// Coinbase transactions only have a single txin by definition.
	if blockchain.IsCoinBaseTx(mtx) {
		// Only include the transaction if the filter map is empty
		// because a coinbase input has no addresses and so would never
		// match a non-empty filter.
		if len(filterAddrMap) != 0 {
			return nil, nil
		}

		txIn := mtx.TxIn[0]
		vinList := make([]hcjson.VinPrevOut, 1)
		vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript)
		amountIn := hcutil.Amount(txIn.ValueIn).ToCoin()
		vinList[0].AmountIn = &amountIn
		vinList[0].Sequence = txIn.Sequence
		return vinList, nil
	}

	// Use a dynamically sized list to accommodate the address filter.
	vinList := make([]hcjson.VinPrevOut, 0, len(mtx.TxIn))

	// Lookup all of the referenced transaction outputs needed to populate
	// the previous output information if requested.
	var originOutputs map[wire.OutPoint]wire.TxOut
	if vinExtra || len(filterAddrMap) > 0 {
		var err error
		originOutputs, err = fetchInputTxos(s, mtx)
		if err != nil {
			return nil, err
		}
	}

	// Stakebase transactions (votes) have two inputs: a null stake base
	// followed by an input consuming a ticket's stakesubmission.
	isSSGen, _ := stake.IsSSGen(mtx)

	for i, txIn := range mtx.TxIn {
		// Handle only the null input of a stakebase differently.
		if isSSGen && i == 0 {
			amountIn := hcutil.Amount(txIn.ValueIn).ToCoin()
			vinEntry := hcjson.VinPrevOut{
				Stakebase: hex.EncodeToString(txIn.SignatureScript),
				AmountIn:  &amountIn,
				Sequence:  txIn.Sequence,
			}
			vinList = append(vinList, vinEntry)
			// No previous outpoints to check against the address filter.
			continue
		}

		// The disassembled string will contain [error] inline if the
		// script doesn't fully parse, so ignore the error here.
		disbuf, _ := txscript.DisasmString(txIn.SignatureScript)

		// Create the basic input entry without the additional optional
		// previous output details which will be added later if
		// requested and available.
		prevOut := &txIn.PreviousOutPoint
		amountIn := hcutil.Amount(txIn.ValueIn).ToCoin()
		vinEntry := hcjson.VinPrevOut{
			Txid:        prevOut.Hash.String(),
			Vout:        prevOut.Index,
			Tree:        prevOut.Tree,
			AmountIn:    &amountIn,
			BlockHeight: &txIn.BlockHeight,
			BlockIndex:  &txIn.BlockIndex,
			Sequence:    txIn.Sequence,
			ScriptSig: &hcjson.ScriptSig{
				Asm: disbuf,
				Hex: hex.EncodeToString(txIn.SignatureScript),
			},
		}

		// Add the entry to the list now if it already passed the
		// filter since the previous output might not be available.
		passesFilter := len(filterAddrMap) == 0
		if passesFilter {
			vinList = append(vinList, vinEntry)
		}

		// Only populate previous output information if requested and
		// available.
		if len(originOutputs) == 0 {
			continue
		}
		originTxOut, ok := originOutputs[*prevOut]
		if !ok {
			continue
		}

		// Ignore the error here since an error means the script
		// couldn't parse and there is no additional information about
		// it anyways.
		_, addrs, _, _ := txscript.ExtractPkScriptAddrs(originTxOut.Version,
			originTxOut.PkScript, chainParams)

		// Encode the addresses while checking if the address passes
		// the filter when needed.
		encodedAddrs := make([]string, len(addrs))
		for j, addr := range addrs {
			encodedAddr := addr.EncodeAddress()
			encodedAddrs[j] = encodedAddr

			// No need to check the map again if the filter already
			// passes.
			if passesFilter {
				continue
			}
			if _, exists := filterAddrMap[encodedAddr]; exists {
				passesFilter = true
			}
		}

		// Ignore the entry if it doesn't pass the filter.
		if !passesFilter {
			continue
		}

		// Add entry to the list if it wasn't already done above.
		if len(filterAddrMap) != 0 {
			vinList = append(vinList, vinEntry)
		}

		// Update the entry with previous output information if
		// requested.
		if vinExtra {
			vinListEntry := &vinList[len(vinList)-1]
			vinListEntry.PrevOut = &hcjson.PrevOut{
				Addresses: encodedAddrs,
				Value:     hcutil.Amount(originTxOut.Value).ToCoin(),
			}
		}
	}

	return vinList, nil
}

// fetchMempoolTxnsForAddress queries the address index for all unconfirmed
// transactions that involve the provided address.  The results will be limited
// by the number to skip and the number requested.
func fetchMempoolTxnsForAddress(s *rpcServer, addr hcutil.Address, numToSkip, numRequested uint32) ([]*hcutil.Tx, uint32) {
	// There are no entries to return when there are less available than
	// the number being skipped.
	mpTxns := s.server.addrIndex.UnconfirmedTxnsForAddress(addr)
	numAvailable := uint32(len(mpTxns))
	if numToSkip > numAvailable {
		return nil, numAvailable
	}

	// Filter the available entries based on the number to skip and number
	// requested.
	rangeEnd := numToSkip + numRequested
	if rangeEnd > numAvailable {
		rangeEnd = numAvailable
	}
	return mpTxns[numToSkip:rangeEnd], numToSkip
}

// handleSearchRawTransactions implements the searchrawtransactions command.
func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	// Respond with an error if the address index is not enabled.
	addrIndex := s.server.addrIndex
	if addrIndex == nil {
		return nil, rpcInternalError("Address index must be "+
			"enabled (--addrindex)", "Configuration")
	}

	// Override the flag for including extra previous output information in
	// each input if needed.
	c := cmd.(*hcjson.SearchRawTransactionsCmd)
	vinExtra := false
	if c.VinExtra != nil {
		vinExtra = *c.VinExtra != 0
	}

	// Including the extra previous output information requires the
	// transaction index.  Currently the address index relies on the
	// transaction index, so this check is redundant, but it's better to be
	// safe in case the address index is ever changed to not rely on it.
	if vinExtra && s.server.txIndex == nil {
		return nil, rpcInternalError("Transaction index must be "+
			"enabled (--txindex)", "Configuration")
	}

	// Attempt to decode the supplied address.
	addr, err := hcutil.DecodeAddress(c.Address)
	if err != nil {
		return nil, rpcAddressKeyError("Could not decode address: %v",
			err)
	}

	// Override the default number of requested entries if needed.  Also,
	// just return now if the number of requested entries is zero to avoid
	// extra work.
	numRequested := 100
	if c.Count != nil {
		numRequested = *c.Count
		if numRequested < 0 {
			numRequested = 1
		}
	}
	if numRequested == 0 {
		return nil, nil
	}

	// Override the default number of entries to skip if needed.
	var numToSkip int
	if c.Skip != nil {
		numToSkip = *c.Skip
		if numToSkip < 0 {
			numToSkip = 0
		}
	}

	// Override the reverse flag if needed.
	var reverse bool
	if c.Reverse != nil {
		reverse = *c.Reverse
	}

	// Add transactions from mempool first if client asked for reverse
	// order.  Otherwise, they will be added last (as needed depending on
	// the requested counts).
	//
	// NOTE: This code doesn't sort by dependency.  This might be something
	// to do in the future for the client's convenience, or leave it to the
	// client.
	numSkipped := uint32(0)
	addressTxns := make([]retrievedTx, 0, numRequested)
	if reverse {
		// Transactions in the mempool are not in a block header yet,
		// so the block header field in the retieved transaction struct
		// is left nil.
		mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr,
			uint32(numToSkip), uint32(numRequested))
		numSkipped += mpSkipped
		for _, tx := range mpTxns {
			addressTxns = append(addressTxns, retrievedTx{tx: tx})
		}
	}

	// Fetch transactions from the database in the desired order if more
	// are needed.
	if len(addressTxns) < numRequested {
		err = s.server.db.View(func(dbTx database.Tx) error {
			regions, dbSkipped, err := addrIndex.TxRegionsForAddress(
				dbTx, addr, uint32(numToSkip)-numSkipped,
				uint32(numRequested-len(addressTxns)), reverse)
			if err != nil {
				return err
			}

			// Load the raw transaction bytes from the database.
			serializedTxns, err := dbTx.FetchBlockRegions(regions)
			if err != nil {
				return err
			}

			// Add the transaction and the hash of the block it is
			// contained in to the list.  Note that the transaction
			// is left serialized here since the caller might have
			// requested non-verbose output and hence there would
			// be no point in deserializing it just to reserialize
			// it later.
			for i, serializedTx := range serializedTxns {
				addressTxns = append(addressTxns, retrievedTx{
					txBytes: serializedTx,
					blkHash: regions[i].Hash,
				})
			}
			numSkipped += dbSkipped

			return nil
		})
		if err != nil {
			context := "Failed to load address index entries"
			return nil, rpcInternalError(err.Error(), context)
		}

	}

	// Add transactions from mempool last if client did not request reverse
	// order and the number of results is still under the number requested.
	if !reverse && len(addressTxns) < numRequested {
		// Transactions in the mempool are not in a block header yet,
		// so the block header field in the retieved transaction struct
		// is left nil.
		mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr,
			uint32(numToSkip)-numSkipped, uint32(numRequested-
				len(addressTxns)))
		numSkipped += mpSkipped
		for _, tx := range mpTxns {
			addressTxns = append(addressTxns, retrievedTx{tx: tx})
		}
	}

	// Address has never been used if neither source yielded any results.
	if len(addressTxns) == 0 {
		return nil, rpcInternalError("No Txns available", "")
	}

	// Serialize all of the transactions to hex.
	hexTxns := make([]string, len(addressTxns))
	for i := range addressTxns {
		// Simply encode the raw bytes to hex when the retrieved
		// transaction is already in serialized form.
		rtx := &addressTxns[i]
		if rtx.txBytes != nil {
			hexTxns[i] = hex.EncodeToString(rtx.txBytes)
			continue
		}

		// Serialize the transaction first and convert to hex when the
		// retrieved transaction is the deserialized structure.
		hexTxns[i], err = messageToHex(rtx.tx.MsgTx())
		if err != nil {
			return nil, err
		}
	}

	// When not in verbose mode, simply return a list of serialized txns.
	if c.Verbose != nil && *c.Verbose == 0 {
		return hexTxns, nil
	}

	// Normalize the provided filter addresses (if any) to ensure there are
	// no duplicates.
	filterAddrMap := make(map[string]struct{})
	if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 {
		for _, addr := range *c.FilterAddrs {
			filterAddrMap[addr] = struct{}{}
		}
	}

	// The verbose flag is set, so generate the JSON object and return it.
	best := s.chain.BestSnapshot()
	chainParams := s.server.chainParams
	srtList := make([]hcjson.SearchRawTransactionsResult, len(addressTxns))
	for i := range addressTxns {
		// The deserialized transaction is needed, so deserialize the
		// retrieved transaction if it's in serialized form (which will
		// be the case when it was lookup up from the database).
		// Otherwise, use the existing deserialized transaction.
		rtx := &addressTxns[i]
		var mtx *wire.MsgTx
		if rtx.tx == nil {
			// Deserialize the transaction.
			mtx = new(wire.MsgTx)
			err := mtx.Deserialize(bytes.NewReader(rtx.txBytes))
			if err != nil {
				context := "Failed to deserialize transaction"
				return nil, rpcInternalError(err.Error(),
					context)
			}
		} else {
			mtx = rtx.tx.MsgTx()
		}

		result := &srtList[i]
		result.Hex = hexTxns[i]
		result.Txid = mtx.TxHash().String()
		result.Vin, err = createVinListPrevOut(s, mtx, chainParams,
			vinExtra, filterAddrMap)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not create vin list")
		}
		result.Vout = createVoutList(mtx, chainParams, filterAddrMap)
		result.Version = int32(mtx.Version)
		result.LockTime = mtx.LockTime

		// Transactions grabbed from the mempool aren't yet in a block,
		// so conditionally fetch block details here.  This will be
		// reflected in the final JSON output (mempool won't have
		// confirmations or block information).
		var blkHeader *wire.BlockHeader
		var blkHashStr string
		var blkHeight int64
		if blkHash := rtx.blkHash; blkHash != nil {
			// Load the raw header bytes from the database.
			var headerBytes []byte
			err := s.server.db.View(func(dbTx database.Tx) error {
				var err error
				headerBytes, err = dbTx.FetchBlockHeader(blkHash)
				return err
			})
			if err != nil {
				return nil, &hcjson.RPCError{
					Code:    hcjson.ErrRPCBlockNotFound,
					Message: "Block not found",
				}
			}

			// Deserialize the block header.
			var header wire.BlockHeader
			err = header.Deserialize(bytes.NewReader(headerBytes))
			if err != nil {
				context := "Failed to deserialize block header"
				return nil, rpcInternalError(err.Error(), context)
			}

			// Get the block height from chain.
			height, err := s.chain.BlockHeightByHash(blkHash)
			if err != nil {
				context := "Failed to obtain block height"
				return nil, rpcInternalError(err.Error(), context)
			}

			blkHeader = &header
			blkHashStr = blkHash.String()
			blkHeight = height
		}

		// Add the block information to the result if there is any.
		if blkHeader != nil {
			// This is not a typo, they are identical in Bitcoin
			// Core as well.
			result.Time = blkHeader.Timestamp.Unix()
			result.Blocktime = blkHeader.Timestamp.Unix()
			result.BlockHash = blkHashStr
			result.Confirmations = uint64(1 + best.Height - blkHeight)
		}
	}

	return srtList, nil
}

// handleSendRawTransaction implements the sendrawtransaction command.
func handleSendRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.SendRawTransactionCmd)
	// Deserialize and send off to tx relay

	allowHighFees := *c.AllowHighFees
	hexStr := c.HexTx
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	serializedTx, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, rpcDecodeHexError(hexStr)
	}
	msgtx := wire.NewMsgTx()
	err = msgtx.Deserialize(bytes.NewReader(serializedTx))
	if err != nil {
		return nil, rpcDeserializationError("Could not decode Tx: %v",
			err)
	}

	tx := hcutil.NewTx(msgtx)
	acceptedTxs, err := s.server.blockManager.ProcessTransaction(tx, false,
		false, allowHighFees)
	if err != nil {
		// When the error is a rule error, it means the transaction was
		// simply rejected as opposed to something actually going
		// wrong, so log it as such.  Otherwise, something really did
		// go wrong, so log it as an actual error.  In both cases, a
		// JSON-RPC error is returned to the client with the
		// deserialization error code (to match bitcoind behavior).
		if _, ok := err.(mempool.RuleError); ok {
			err = fmt.Errorf("Rejected transaction %v: %v", tx.Hash(),
				err)
			rpcsLog.Debugf("%v", err)
			return nil, rpcRuleError("%v", err)
		}

		err = fmt.Errorf("failed to process transaction %v: %v",
			tx.Hash(), err)
		rpcsLog.Errorf("%v", err)
		return nil, rpcDeserializationError("rejected: %v", err)
	}

	s.server.AnnounceNewTransactions(acceptedTxs)

	// Keep track of all the sendrawtransaction request txns so that they
	// can be rebroadcast if they don't make their way into a block.
	iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash())
	s.server.AddRebroadcastInventory(iv, tx)

	return tx.Hash().String(), nil
}

// handleSetGenerate implements the setgenerate command.
func handleSetGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.SetGenerateCmd)

	// Disable generation regardless of the provided generate flag if the
	// maximum number of threads (goroutines for our purposes) is 0.
	// Otherwise enable or disable it depending on the provided flag.
	generate := c.Generate
	genProcLimit := -1
	if c.GenProcLimit != nil {
		genProcLimit = *c.GenProcLimit
	}
	if genProcLimit == 0 {
		generate = false
	}

	if !generate {
		s.server.cpuMiner.Stop()
	} else {
		// Respond with an error if there are no addresses to pay the
		// created blocks to.
		if len(cfg.miningAddrs) == 0 {
			return nil, rpcInternalError("No payment addresses "+
				"specified via --miningaddr", "Configuration")
		}

		// It's safe to call start even if it's already started.
		s.server.cpuMiner.SetNumWorkers(int32(genProcLimit))
		s.server.cpuMiner.Start()
	}
	return nil, nil
}

// handleStop implements the stop command.
func handleStop(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	select {
	case s.requestProcessShutdown <- struct{}{}:
	default:
	}
	return "hcd stopping.", nil
}

// handleSubmitBlock implements the submitblock command.
func handleSubmitBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.SubmitBlockCmd)
	// Deserialize the submitted block.
	hexStr := c.HexBlock
	if len(hexStr)%2 != 0 {
		hexStr = "0" + c.HexBlock
	}
	serializedBlock, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Block decode")
	}

	block, err := hcutil.NewBlockFromBytes(serializedBlock)
	if err != nil {
		return nil, rpcInternalError(err.Error(), "Block decode")
	}

	_, err = s.server.blockManager.ProcessBlock(block, blockchain.BFNone)
	if err != nil {
		return fmt.Sprintf("rejected: %v", err), nil
	}

	rpcsLog.Infof("Accepted block %s via submitblock", block.Hash())
	return nil, nil
}

// min gets the minimum amount from a slice of amounts.
func min(s []hcutil.Amount) hcutil.Amount {
	if len(s) == 0 {
		return 0
	}

	min := s[0]
	for i := range s {
		if s[i] < min {
			min = s[i]
		}
	}

	return min
}

// max gets the maximum amount from a slice of amounts.
func max(s []hcutil.Amount) hcutil.Amount {
	max := hcutil.Amount(0)
	for i := range s {
		if s[i] > max {
			max = s[i]
		}
	}

	return max
}

// mean gets the mean amount from a slice of amounts.
func mean(s []hcutil.Amount) hcutil.Amount {
	sum := hcutil.Amount(0)
	for i := range s {
		sum += s[i]
	}

	if len(s) == 0 {
		return 0
	}

	return sum / hcutil.Amount(len(s))
}

// median gets the median amount from a slice of amounts.
func median(s []hcutil.Amount) hcutil.Amount {
	if len(s) == 0 {
		return 0
	}

	sort.Sort(hcutil.AmountSorter(s))

	middle := len(s) / 2

	if len(s) == 0 {
		return 0
	} else if (len(s) % 2) != 0 {
		return s[middle]
	}
	return (s[middle] + s[middle-1]) / 2
}

// stdDev gets the standard deviation amount from a slice of amounts.
func stdDev(s []hcutil.Amount) hcutil.Amount {
	var total float64
	mean := mean(s)

	for i := range s {
		total += math.Pow(s[i].ToCoin()-mean.ToCoin(), 2)
	}
	if len(s)-1 == 0 {
		return 0
	}
	v := total / float64(len(s)-1)

	// Not concerned with an error here, it'll return
	// zero if the amount is too small.
	amt, _ := hcutil.NewAmount(math.Sqrt(v))

	return amt
}

// feeInfoForMempool returns the fee information for the passed tx type in the
// memory pool.
func feeInfoForMempool(s *rpcServer, txType stake.TxType) *hcjson.FeeInfoMempool {
	txDs := s.server.txMemPool.TxDescs()
	ticketFees := make([]hcutil.Amount, 0, len(txDs))
	for _, txD := range txDs {
		if txD.Type == txType {
			feePerKb := (hcutil.Amount(txD.Fee)) * 1000 /
				hcutil.Amount(txD.Tx.MsgTx().SerializeSize())
			ticketFees = append(ticketFees, feePerKb)
		}
	}

	return &hcjson.FeeInfoMempool{
		Number: uint32(len(ticketFees)),
		Min:    min(ticketFees).ToCoin(),
		Max:    max(ticketFees).ToCoin(),
		Mean:   mean(ticketFees).ToCoin(),
		Median: median(ticketFees).ToCoin(),
		StdDev: stdDev(ticketFees).ToCoin(),
	}
}

// calcFee calculates the fee of a transaction that has its fraud proofs
// properly set.
func calcFeePerKb(tx *hcutil.Tx) hcutil.Amount {
	var in hcutil.Amount
	for _, txIn := range tx.MsgTx().TxIn {
		in += hcutil.Amount(txIn.ValueIn)
	}
	var out hcutil.Amount
	for _, txOut := range tx.MsgTx().TxOut {
		out += hcutil.Amount(txOut.Value)
	}

	return ((in - out) * 1000) / hcutil.Amount(tx.MsgTx().SerializeSize())
}

// feeInfoForBlock fetches the ticket fee information for a given tx type in a
// block.
func ticketFeeInfoForBlock(s *rpcServer, height int64, txType stake.TxType) (*hcjson.FeeInfoBlock, error) {
	bl, err := s.chain.BlockByHeight(height)
	if err != nil {
		return nil, err
	}

	txNum := 0
	switch txType {
	case stake.TxTypeRegular:
		txNum = len(bl.MsgBlock().Transactions) - 1
	case stake.TxTypeSStx:
		txNum = int(bl.MsgBlock().Header.FreshStake)
	case stake.TxTypeSSGen:
		txNum = int(bl.MsgBlock().Header.Voters)
	case stake.TxTypeSSRtx:
		txNum = int(bl.MsgBlock().Header.Revocations)
	}

	txFees := make([]hcutil.Amount, txNum)
	itr := 0
	if txType == stake.TxTypeRegular {
		for i, tx := range bl.Transactions() {
			// Skip the coin base.
			if i == 0 {
				continue
			}

			txFees[itr] = calcFeePerKb(tx)
			itr++
		}
	} else {
		for _, stx := range bl.STransactions() {
			thisTxType := stake.DetermineTxType(stx.MsgTx())
			if thisTxType == txType {
				txFees[itr] = calcFeePerKb(stx)
				itr++
			}
		}
	}

	return &hcjson.FeeInfoBlock{
		Height: uint32(height),
		Number: uint32(txNum),
		Min:    min(txFees).ToCoin(),
		Max:    max(txFees).ToCoin(),
		Mean:   mean(txFees).ToCoin(),
		Median: median(txFees).ToCoin(),
		StdDev: stdDev(txFees).ToCoin(),
	}, nil
}

// ticketFeeInfoForRange fetches the ticket fee information for a given range
// from [start, end).
func ticketFeeInfoForRange(s *rpcServer, start int64, end int64, txType stake.TxType) (*hcjson.FeeInfoWindow, error) {
	hashes, err := s.chain.HeightRange(start, end)
	if err != nil {
		return nil, err
	}

	var txFees []hcutil.Amount
	for i := range hashes {
		bl, err := s.chain.BlockByHash(&hashes[i])
		if err != nil {
			return nil, err
		}

		if txType == stake.TxTypeRegular {
			for i, tx := range bl.Transactions() {
				// Skip the coin base.
				if i == 0 {
					continue
				}

				txFees = append(txFees, calcFeePerKb(tx))
			}
		} else {
			for _, stx := range bl.STransactions() {
				thisTxType := stake.DetermineTxType(stx.MsgTx())
				if thisTxType == txType {
					txFees = append(txFees, calcFeePerKb(stx))
				}
			}
		}
	}

	return &hcjson.FeeInfoWindow{
		StartHeight: uint32(start),
		EndHeight:   uint32(end),
		Number:      uint32(len(txFees)),
		Min:         min(txFees).ToCoin(),
		Max:         max(txFees).ToCoin(),
		Mean:        mean(txFees).ToCoin(),
		Median:      median(txFees).ToCoin(),
		StdDev:      stdDev(txFees).ToCoin(),
	}, nil
}

// handleTicketFeeInfo implements the ticketfeeinfo command.
func handleTicketFeeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.TicketFeeInfoCmd)

	s.server.blockManager.chainState.Lock()
	bestHeight := s.server.blockManager.chainState.newestHeight
	s.server.blockManager.chainState.Unlock()

	// Memory pool first.
	feeInfoMempool := feeInfoForMempool(s, stake.TxTypeSStx)

	// Blocks requested, descending from the chain tip.
	var feeInfoBlocks []hcjson.FeeInfoBlock
	blocks := uint32(0)
	if c.Blocks != nil {
		blocks = *c.Blocks
	}
	if blocks > 0 {
		start := bestHeight
		end := bestHeight - int64(blocks)

		for i := start; i > end; i-- {
			feeInfo, err := ticketFeeInfoForBlock(s, i, stake.TxTypeSStx)
			if err != nil {
				return nil, rpcInternalError(err.Error(),
					"Could not obtain ticket fee info")
			}
			feeInfoBlocks = append(feeInfoBlocks, *feeInfo)
		}
	}

	var feeInfoWindows []hcjson.FeeInfoWindow
	windows := uint32(0)
	if c.Windows != nil {
		windows = *c.Windows
	}
	if windows > 0 {
		// The first window is special because it may not be finished.
		// Perform this first and return if it's the only window the
		// user wants. Otherwise, append and continue.
		winLen := s.server.chainParams.StakeDiffWindowSize
		lastChange := (bestHeight / winLen) * winLen

		feeInfo, err := ticketFeeInfoForRange(s, lastChange, bestHeight+1,
			stake.TxTypeSStx)
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not obtain ticket fee info")
		}
		feeInfoWindows = append(feeInfoWindows, *feeInfo)

		// We need data on windows from before this. Start from
		// the last adjustment and move backwards through window
		// lengths, calulating the fees data and appending it
		// each time.
		if windows > 1 {
			// Go down to the last height requested, except
			// in the case that the user has specified to
			// many windows. In that case, just proceed to the
			// first block.
			end := int64(-1)
			if lastChange-int64(windows)*winLen > end {
				end = lastChange - int64(windows)*winLen
			}
			for i := lastChange; i > end+winLen; i -= winLen {
				feeInfo, err := ticketFeeInfoForRange(s, i-winLen, i,
					stake.TxTypeSStx)
				if err != nil {
					return nil, rpcInternalError(err.Error(),
						"Could not obtain ticket fee info")
				}
				feeInfoWindows = append(feeInfoWindows, *feeInfo)
			}
		}
	}

	return &hcjson.TicketFeeInfoResult{
		FeeInfoMempool: *feeInfoMempool,
		FeeInfoBlocks:  feeInfoBlocks,
		FeeInfoWindows: feeInfoWindows,
	}, nil
}

// handleTicketsForAddress implements the ticketsforaddress command.
func handleTicketsForAddress(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.TicketsForAddressCmd)

	addr, err := hcutil.DecodeAddress(c.Address)
	if err != nil {
		return nil, rpcInvalidError("Invalid address: %v", err)
	}

	tickets, err := s.server.blockManager.chain.TicketsWithAddress(addr)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not obtain tickets")
	}

	ticketStrings := make([]string, len(tickets))
	itr := 0
	for _, ticket := range tickets {
		ticketStrings[itr] = ticket.String()
		itr++
	}

	reply := &hcjson.TicketsForAddressResult{
		Tickets: ticketStrings,
	}
	return reply, nil
}

// handleTicketVWAP implements the ticketvwap command.
func handleTicketVWAP(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.TicketVWAPCmd)

	// The default VWAP is for the past WorkDiffWindows * WorkDiffWindowSize
	// many blocks.
	_, bestHeight := s.server.blockManager.chainState.Best()
	start := uint32(0)
	if c.Start == nil {
		toEval := activeNetParams.WorkDiffWindows *
			activeNetParams.WorkDiffWindowSize
		startI64 := bestHeight - toEval

		// Use 1 as the first block if there aren't
		// enough blocks.
		if startI64 <= 0 {
			start = 1
		} else {
			start = uint32(startI64)
		}
	} else {
		start = *c.Start
	}

	end := uint32(bestHeight)
	if c.End != nil {
		end = *c.End
	}
	if start > end {
		return nil, rpcInvalidError("Start height %v is beyond end "+
			"height %v", start, end)
	}
	if end > uint32(bestHeight) {
		return nil, rpcInvalidError("End height %v is beyond "+
			"blockchain tip height %v", end, bestHeight)
	}

	// Calculate the volume weighted average price of a ticket for the
	// given range.
	ticketNum := int64(0)
	totalValue := int64(0)
	for i := start; i <= end; i++ {
		blockHeader, err := s.chain.HeaderByHeight(int64(i))
		if err != nil {
			return nil, rpcInternalError(err.Error(),
				"Could not obtain header")
		}

		ticketNum += int64(blockHeader.FreshStake)
		totalValue += blockHeader.SBits * int64(blockHeader.FreshStake)
	}
	vwap := int64(0)
	if ticketNum > 0 {
		vwap = totalValue / ticketNum
	}

	return hcutil.Amount(vwap).ToCoin(), nil
}

// handleTxFeeInfo implements the txfeeinfo command.
func handleTxFeeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.TxFeeInfoCmd)

	s.server.blockManager.chainState.Lock()
	bestHeight := s.server.blockManager.chainState.newestHeight
	s.server.blockManager.chainState.Unlock()

	// Memory pool first.
	feeInfoMempool := feeInfoForMempool(s, stake.TxTypeRegular)

	// Blocks requested, descending from the chain tip.
	var feeInfoBlocks []hcjson.FeeInfoBlock
	blocks := uint32(0)
	if c.Blocks != nil {
		blocks = *c.Blocks
	}
	if blocks > 0 {
		start := bestHeight
		end := bestHeight - int64(blocks)

		for i := start; i > end; i-- {
			feeInfo, err := ticketFeeInfoForBlock(s, i,
				stake.TxTypeRegular)
			if err != nil {
				return nil, rpcInternalError(err.Error(),
					"Could not obtain ticket fee info")
			}
			feeInfoBlocks = append(feeInfoBlocks, *feeInfo)
		}
	}

	// Get the fee info for the range requested, unless none is given.  The
	// default range is for the past WorkDiffWindowSize many blocks.
	var feeInfoRange hcjson.FeeInfoRange

	start := uint32(0)
	if c.RangeStart == nil {
		toEval := activeNetParams.WorkDiffWindowSize
		startI64 := bestHeight - toEval

		// Use 1 as the first block if there aren't enough blocks.
		if startI64 <= 0 {
			start = 1
		} else {
			start = uint32(startI64)
		}
	} else {
		start = *c.RangeStart
	}

	end := uint32(bestHeight)
	if c.RangeEnd != nil {
		end = *c.RangeEnd
	}
	if start > end {
		return nil, rpcInvalidError("Start height %v is beyond end "+
			"height %v", start, end)
	}
	if end > uint32(bestHeight) {
		return nil, rpcInvalidError("End height %v is beyond "+
			"blockchain tip height %v", end, bestHeight)
	}

	feeInfo, err := ticketFeeInfoForRange(s, int64(start), int64(end+1),
		stake.TxTypeRegular)
	if err != nil {
		return nil, rpcInternalError(err.Error(),
			"Could not obtain ticket fee info")
	}

	feeInfoRange = hcjson.FeeInfoRange{
		Number: feeInfo.Number,
		Min:    feeInfo.Min,
		Max:    feeInfo.Max,
		Mean:   feeInfo.Mean,
		Median: feeInfo.Median,
		StdDev: feeInfo.StdDev,
	}

	return &hcjson.TxFeeInfoResult{
		FeeInfoMempool: *feeInfoMempool,
		FeeInfoBlocks:  feeInfoBlocks,
		FeeInfoRange:   feeInfoRange,
	}, nil
}

// handleValidateAddress implements the validateaddress command.
func handleValidateAddress(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.ValidateAddressCmd)

	result := hcjson.ValidateAddressChainResult{}
	addr, err := hcutil.DecodeAddress(c.Address)
	if err != nil || !addr.IsForNet(s.server.chainParams) {
		// Return the default value (false) for IsValid.
		return result, nil
	}

	result.Address = addr.EncodeAddress()
	result.IsValid = true

	return result, nil
}

func verifyChain(s *rpcServer, level, depth int64) error {
	best := s.chain.BestSnapshot()
	finishHeight := best.Height - depth
	if finishHeight < 0 {
		finishHeight = 0
	}
	rpcsLog.Infof("Verifying chain for %d blocks at level %d",
		best.Height-finishHeight, level)

	for height := best.Height; height > finishHeight; height-- {
		// Level 0 just looks up the block.
		block, err := s.chain.BlockByHeight(height)
		if err != nil {
			rpcsLog.Errorf("Verify is unable to fetch block at "+
				"height %d: %v", height, err)
			return err
		}

		// Level 1 does basic chain sanity checks.
		if level > 0 {
			err := blockchain.CheckBlockSanity(block,
				s.server.timeSource,
				activeNetParams.Params)
			if err != nil {
				rpcsLog.Errorf("Verify is unable to validate "+
					"block at hash %v height %d: %v",
					block.Hash(), height, err)
				return err
			}
		}
	}
	rpcsLog.Infof("Chain verify completed successfully")

	return nil
}

// handleVerifyChain implements the verifychain command.
func handleVerifyChain(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.VerifyChainCmd)

	var checkLevel, checkDepth int64
	if c.CheckLevel != nil {
		checkLevel = *c.CheckLevel
	}
	if c.CheckDepth != nil {
		checkDepth = *c.CheckDepth
	}

	err := verifyChain(s, checkLevel, checkDepth)
	return err == nil, nil
}

// handleVerifyMessage implements the verifymessage command.
func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*hcjson.VerifyMessageCmd)

	// Decode the provided address.
	addr, err := hcutil.DecodeAddress(c.Address)
	if err != nil {
		return nil, rpcAddressKeyError("Could not decode address: %v",
			err)
	}

	// Only P2PKH addresses are valid for signing.
	if _, ok := addr.(*hcutil.AddressPubKeyHash); !ok {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCType,
			Message: "Address is not a pay-to-pubkey-hash address",
		}
	}

	// Decode base64 signature.
	sig, err := base64.StdEncoding.DecodeString(c.Signature)
	if err != nil {
		return nil, &hcjson.RPCError{
			Code:    hcjson.ErrRPCParse.Code,
			Message: "Malformed base64 encoding: " + err.Error(),
		}
	}

	// Validate the signature - this just shows that it was valid at all.
	// we will compare it with the key next.
	var buf bytes.Buffer
	wire.WriteVarString(&buf, 0, "Hc Signed Message:\n")
	wire.WriteVarString(&buf, 0, c.Message)
	expectedMessageHash := chainhash.HashB(buf.Bytes())
	pk, wasCompressed, err := chainec.Secp256k1.RecoverCompact(sig,
		expectedMessageHash)
	if err != nil {
		// Mirror Bitcoin Core behavior, which treats error in
		// RecoverCompact as invalid signature.
		return false, nil
	}

	// Reconstruct the pubkey hash.
	hcPK := pk
	var serializedPK []byte
	if wasCompressed {
		serializedPK = hcPK.SerializeCompressed()
	} else {
		serializedPK = hcPK.SerializeUncompressed()
	}
	address, err := hcutil.NewAddressSecpPubKey(serializedPK,
		activeNetParams.Params)
	if err != nil {
		// Again mirror Bitcoin Core behavior, which treats error in
		// public key reconstruction as invalid signature.
		return false, nil
	}

	// Return boolean if addresses match.
	return address.EncodeAddress() == c.Address, nil
}

// handleVerifyBlissMessage implements the verifyblissmessage command.
func handleVerifyBlissMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {

	icmd := cmd.(*hcjson.VerifyBlissMessageCmd)
	var valid bool

	pubkey, err := hex.DecodeString(icmd.PubKey)
	if err != nil {
		return nil, err
	}
	key, err := bliss.Bliss.ParsePubKey(pubkey)
	if err != nil {
		return nil, err
	}

	var buf bytes.Buffer
	wire.WriteVarString(&buf, 0, "Hc Signed Message:\n")
	wire.WriteVarString(&buf, 0, icmd.Message)
	messageHash := chainhash.HashB(buf.Bytes())

	sig, err := base64.StdEncoding.DecodeString(icmd.Signature)
	if err != nil {
		return nil, err
	}

	valid, err = bliss.VerifyCompact(key, messageHash, sig)
	if err != nil {
		return nil, err
	}

	return valid, nil
}

// handleVersion implements the version command.
func handleVersion(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
	result := map[string]hcjson.VersionResult{
		"hcdjsonrpcapi": {
			VersionString: jsonrpcSemverString,
			Major:         jsonrpcSemverMajor,
			Minor:         jsonrpcSemverMinor,
			Patch:         jsonrpcSemverPatch,
		},
	}
	return result, nil
}

// rpcServer holds the items the rpc server may need to access (config,
// shutdown, main server, etc.)
type rpcServer struct {
	started                int32
	shutdown               int32
	policy                 *mining.Policy
	server                 *server
	chain                  *blockchain.BlockChain
	authsha                [sha256.Size]byte
	limitauthsha           [sha256.Size]byte
	ntfnMgr                *wsNotificationManager
	numClients             int32
	statusLines            map[int]string
	statusLock             sync.RWMutex
	wg                     sync.WaitGroup
	listeners              []net.Listener
	workState              *workState
	gbtWorkState           *gbtWorkState
	templatePool           map[[merkleRootPairSize]byte]*workStateBlockInfo
	helpCacher             *helpCacher
	requestProcessShutdown chan struct{}
	quit                   chan int

	// coin supply caching values
	coinSupplyMtx    sync.Mutex
	coinSupplyHeight int64
	coinSupplyTotal  int64
}

// httpStatusLine returns a response Status-Line (RFC 2616 Section 6.1) for the
// given request and response status code.  This function was lifted and
// adapted from the standard library HTTP server code since it's not exported.
func (s *rpcServer) httpStatusLine(req *http.Request, code int) string {
	// Fast path:
	key := code
	proto11 := req.ProtoAtLeast(1, 1)
	if !proto11 {
		key = -key
	}
	s.statusLock.RLock()
	line, ok := s.statusLines[key]
	s.statusLock.RUnlock()
	if ok {
		return line
	}

	// Slow path:
	proto := "HTTP/1.0"
	if proto11 {
		proto = "HTTP/1.1"
	}
	codeStr := strconv.Itoa(code)
	text := http.StatusText(code)
	if text != "" {
		line = proto + " " + codeStr + " " + text + "\r\n"
		s.statusLock.Lock()
		s.statusLines[key] = line
		s.statusLock.Unlock()
	} else {
		text = "status code " + codeStr
		line = proto + " " + codeStr + " " + text + "\r\n"
	}

	return line
}

// writeHTTPResponseHeaders writes the necessary response headers prior to
// writing an HTTP body given a request to use for protocol negotiation,
// headers to write, a status code, and a writer.
func (s *rpcServer) writeHTTPResponseHeaders(req *http.Request, headers http.Header, code int, w io.Writer) error {
	_, err := io.WriteString(w, s.httpStatusLine(req, code))
	if err != nil {
		return err
	}

	err = headers.Write(w)
	if err != nil {
		return err
	}

	_, err = io.WriteString(w, "\r\n")
	return err
}

// Stop is used by server.go to stop the rpc listener.
func (s *rpcServer) Stop() error {
	if atomic.AddInt32(&s.shutdown, 1) != 1 {
		rpcsLog.Infof("RPC server is already in the process of " +
			"shutting down")
		return nil
	}
	rpcsLog.Warnf("RPC server shutting down")
	for _, listener := range s.listeners {
		err := listener.Close()
		if err != nil {
			rpcsLog.Errorf("Problem shutting down rpc: %v", err)
			return err
		}
	}
	s.ntfnMgr.Shutdown()
	s.ntfnMgr.WaitForShutdown()
	close(s.quit)
	s.wg.Wait()
	rpcsLog.Infof("RPC server shutdown complete")
	return nil
}

// RequestedProcessShutdown returns a channel that is sent to when an
// authorized RPC client requests the process to shutdown.  If the request can
// not be read immediately, it is dropped.
func (s *rpcServer) RequestedProcessShutdown() <-chan struct{} {
	return s.requestProcessShutdown
}

// limitConnections responds with a 503 service unavailable and returns true if
// adding another client would exceed the maximum allow RPC clients.
//
// This function is safe for concurrent access.
func (s *rpcServer) limitConnections(w http.ResponseWriter, remoteAddr string) bool {
	if int(atomic.LoadInt32(&s.numClients)+1) > cfg.RPCMaxClients {
		rpcsLog.Infof("Max RPC clients exceeded [%d] - "+
			"disconnecting client %s", cfg.RPCMaxClients,
			remoteAddr)
		http.Error(w, "503 Too busy.  Try again later.",
			http.StatusServiceUnavailable)
		return true
	}
	return false
}

// incrementClients adds one to the number of connected RPC clients.  Note this
// only applies to standard clients.  Websocket clients have their own limits
// and are tracked separately.
//
// This function is safe for concurrent access.
func (s *rpcServer) incrementClients() {
	atomic.AddInt32(&s.numClients, 1)
}

// decrementClients subtracts one from the number of connected RPC clients.
// Note this only applies to standard clients.  Websocket clients have their
// own limits and are tracked separately.
//
// This function is safe for concurrent access.
func (s *rpcServer) decrementClients() {
	atomic.AddInt32(&s.numClients, -1)
}

// checkAuth checks the HTTP Basic authentication supplied by a wallet or RPC
// client in the HTTP request r.  If the supplied authentication does not match
// the username and password expected, a non-nil error is returned.
//
// This check is time-constant.
//
// The first bool return value signifies auth success (true if successful) and
// the second bool return value specifies whether the user can change the state
// of the server (true) or whether the user is limited (false). The second is
// always false if the first is.
func (s *rpcServer) checkAuth(r *http.Request, require bool) (bool, bool, error) {
	authhdr := r.Header["Authorization"]
	if len(authhdr) <= 0 {
		if require {
			rpcsLog.Warnf("RPC authentication failure from %s",
				r.RemoteAddr)
			return false, false, errors.New("auth failure")
		}

		return false, false, nil
	}

	authsha := sha256.Sum256([]byte(authhdr[0]))

	// Check for limited auth first as in environments with limited users,
	// those are probably expected to have a higher volume of calls
	limitcmp := subtle.ConstantTimeCompare(authsha[:], s.limitauthsha[:])
	if limitcmp == 1 {
		return true, false, nil
	}

	// Check for admin-level auth
	cmp := subtle.ConstantTimeCompare(authsha[:], s.authsha[:])
	if cmp == 1 {
		return true, true, nil
	}

	// Request's auth doesn't match either user
	rpcsLog.Warnf("RPC authentication failure from %s", r.RemoteAddr)
	return false, false, errors.New("auth failure")
}

// parsedRPCCmd represents a JSON-RPC request object that has been parsed into
// a known concrete command along with any error that might have happened while
// parsing it.
type parsedRPCCmd struct {
	id     interface{}
	method string
	cmd    interface{}
	err    *hcjson.RPCError
}

// standardCmdResult checks that a parsed command is a standard Bitcoin
// JSON-RPC command and runs the appropriate handler to reply to the command.
// Any commands which are not recognized or not implemented will return an
// error suitable for use in replies.
func (s *rpcServer) standardCmdResult(cmd *parsedRPCCmd, closeChan <-chan struct{}) (interface{}, error) {
	handler, ok := rpcHandlers[cmd.method]
	if ok {
		goto handled
	}
	_, ok = rpcAskWallet[cmd.method]
	if ok {
		handler = handleAskWallet
		goto handled
	}
	_, ok = rpcUnimplemented[cmd.method]
	if ok {
		handler = handleUnimplemented
		goto handled
	}
	return nil, hcjson.ErrRPCMethodNotFound
handled:

	return handler(s, cmd.cmd, closeChan)
}

// parseCmd parses a JSON-RPC request object into known concrete command.  The
// err field of the returned parsedRPCCmd struct will contain an RPC error that
// is suitable for use in replies if the command is invalid in some way such as
// an unregistered command or invalid parameters.
func parseCmd(request *hcjson.Request) *parsedRPCCmd {
	var parsedCmd parsedRPCCmd
	parsedCmd.id = request.ID
	parsedCmd.method = request.Method

	cmd, err := hcjson.UnmarshalCmd(request)
	if err != nil {
		// When the error is because the method is not registered,
		// produce a method not found RPC error.
		if jerr, ok := err.(hcjson.Error); ok &&
			jerr.Code == hcjson.ErrUnregisteredMethod {

			parsedCmd.err = hcjson.ErrRPCMethodNotFound
			return &parsedCmd
		}

		// Otherwise, some type of invalid parameters is the cause, so
		// produce the equivalent RPC error.
		parsedCmd.err = rpcInvalidError("Parse error: %v", err)
		return &parsedCmd
	}

	parsedCmd.cmd = cmd
	return &parsedCmd
}

// createMarshalledReply returns a new marshalled JSON-RPC response given the
// passed parameters.  It will automatically convert errors that are not of
// the type *hcjson.RPCError to the appropriate type as needed.
func createMarshalledReply(id, result interface{}, replyErr error) ([]byte, error) {
	var jsonErr *hcjson.RPCError
	if replyErr != nil {
		if jErr, ok := replyErr.(*hcjson.RPCError); ok {
			jsonErr = jErr
		} else {
			jsonErr = rpcInternalError(replyErr.Error(), "")
		}
	}

	return hcjson.MarshalResponse(id, result, jsonErr)
}

// jsonRPCRead handles reading and responding to RPC messages.
func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin bool) {
	if atomic.LoadInt32(&s.shutdown) != 0 {
		return
	}

	// Read and close the JSON-RPC request body from the caller.
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	if err != nil {
		errMsg := fmt.Sprintf("error reading JSON message: %v", err)
		errCode := http.StatusBadRequest
		http.Error(w, strconv.Itoa(errCode)+" "+errMsg,
			errCode)
		return
	}

	// Unfortunately, the http server doesn't provide the ability to change
	// the read deadline for the new connection and having one breaks long
	// polling.  However, not having a read deadline on the initial
	// connection would mean clients can connect and idle forever.  Thus,
	// hijack the connecton from the HTTP server, clear the read deadline,
	// and handle writing the response manually.
	hj, ok := w.(http.Hijacker)
	if !ok {
		errMsg := "webserver doesn't support hijacking"
		rpcsLog.Warnf(errMsg)
		errCode := http.StatusInternalServerError
		http.Error(w, strconv.Itoa(errCode)+" "+errMsg,
			errCode)
		return
	}
	conn, buf, err := hj.Hijack()
	if err != nil {
		rpcsLog.Warnf("Failed to hijack HTTP connection: %v", err)
		errCode := http.StatusInternalServerError
		http.Error(w, strconv.Itoa(errCode)+" "+
			err.Error(), errCode)
		return
	}
	defer conn.Close()
	defer buf.Flush()
	conn.SetReadDeadline(timeZeroVal)

	// Attempt to parse the raw body into a JSON-RPC request.
	var responseID interface{}
	var jsonErr error
	var result interface{}
	var request hcjson.Request
	if err := json.Unmarshal(body, &request); err != nil {
		jsonErr = &hcjson.RPCError{
			Code: hcjson.ErrRPCParse.Code,
			Message: fmt.Sprintf("Failed to parse request: %v",
				err),
		}
	}
	if jsonErr == nil {
		// Requests with no ID (notifications) must not have a response
		// per the JSON-RPC spec.
		if request.ID == nil {
			return
		}

		// The parse was at least successful enough to have an ID so
		// set it for the response.
		responseID = request.ID

		// Setup a close notifier.  Since the connection is hijacked,
		// the CloseNotifer on the ResponseWriter is not available.
		closeChan := make(chan struct{}, 1)
		go func() {
			_, err := conn.Read(make([]byte, 1))
			if err != nil {
				close(closeChan)
			}
		}()

		// Check if the user is limited and set error if method
		// unauthorized
		if !isAdmin {
			if _, ok := rpcLimited[request.Method]; !ok {
				jsonErr = rpcInvalidError("limited user not " +
					"authorized for this method")
			}
		}

		if jsonErr == nil {
			// Attempt to parse the JSON-RPC request into a known
			// concrete command.
			parsedCmd := parseCmd(&request)
			if parsedCmd.err != nil {
				jsonErr = parsedCmd.err
			} else {
				result, jsonErr = s.standardCmdResult(parsedCmd,
					closeChan)
			}
		}
	}

	// Marshal the response.
	msg, err := createMarshalledReply(responseID, result, jsonErr)
	if err != nil {
		rpcsLog.Errorf("Failed to marshal reply: %v", err)
		return
	}

	// Write the response.
	err = s.writeHTTPResponseHeaders(r, w.Header(), http.StatusOK, buf)
	if err != nil {
		rpcsLog.Error(err)
		return
	}
	if _, err := buf.Write(msg); err != nil {
		rpcsLog.Errorf("Failed to write marshalled reply: %v", err)
	}
}

// jsonAuthFail sends a message back to the client if the http auth is rejected.
func jsonAuthFail(w http.ResponseWriter) {
	w.Header().Add("WWW-Authenticate", `Basic realm="hcd RPC"`)
	http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
}

// Start is used by server.go to start the rpc listener.
func (s *rpcServer) Start() {
	if atomic.AddInt32(&s.started, 1) != 1 {
		return
	}

	rpcsLog.Trace("Starting RPC server")
	rpcServeMux := http.NewServeMux()
	httpServer := &http.Server{
		Handler: rpcServeMux,

		// Timeout connections which don't complete the initial
		// handshake within the allowed timeframe.
		ReadTimeout: time.Second * rpcAuthTimeoutSeconds,
	}
	rpcServeMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Connection", "close")
		w.Header().Set("Content-Type", "application/json")
		r.Close = true

		// Limit the number of connections to max allowed.
		if s.limitConnections(w, r.RemoteAddr) {
			return
		}

		// Keep track of the number of connected clients.
		s.incrementClients()
		defer s.decrementClients()
		_, isAdmin, err := s.checkAuth(r, true)
		if err != nil {
			jsonAuthFail(w)
			return
		}

		// Read and respond to the request.
		s.jsonRPCRead(w, r, isAdmin)
	})

	// Websocket endpoint.
	rpcServeMux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		authenticated, isAdmin, err := s.checkAuth(r, false)
		if err != nil {
			jsonAuthFail(w)
			return
		}

		// Attempt to upgrade the connection to a websocket connection
		// using the default size for read/write buffers.
		ws, err := websocket.Upgrade(w, r, nil, 0, 0)
		if err != nil {
			if _, ok := err.(websocket.HandshakeError); !ok {
				rpcsLog.Errorf("Unexpected websocket error: %v",
					err)
			}
			http.Error(w, "400 Bad Request.", http.StatusBadRequest)
			return
		}
		s.WebsocketHandler(ws, r.RemoteAddr, authenticated, isAdmin)
	})

	for _, listener := range s.listeners {
		s.wg.Add(1)
		go func(listener net.Listener) {
			rpcsLog.Infof("RPC server listening on %s",
				listener.Addr())
			httpServer.Serve(listener)
			rpcsLog.Tracef("RPC listener done for %s",
				listener.Addr())
			s.wg.Done()
		}(listener)
	}

	s.ntfnMgr.Start()
}

// genCertPair generates a key/cert pair to the paths provided.
func genCertPair(certFile, keyFile string) error {
	rpcsLog.Infof("Generating TLS certificates...")

	org := "hcd autogenerated cert"
	validUntil := time.Now().Add(10 * 365 * 24 * time.Hour)
	cert, key, err := hcutil.NewTLSCertPair(elliptic.P521(), org,
		validUntil, nil)
	if err != nil {
		return err
	}

	// Write cert and key files.
	if err = ioutil.WriteFile(certFile, cert, 0666); err != nil {
		return err
	}
	if err = ioutil.WriteFile(keyFile, key, 0600); err != nil {
		os.Remove(certFile)
		return err
	}

	rpcsLog.Infof("Done generating TLS certificates")
	return nil
}

// newRPCServer returns a new instance of the rpcServer struct.
func newRPCServer(listenAddrs []string, policy *mining.Policy, s *server) (*rpcServer, error) {
	rpc := rpcServer{
		policy:                 policy,
		server:                 s,
		chain:                  s.blockManager.chain,
		statusLines:            make(map[int]string),
		workState:              newWorkState(),
		templatePool:           make(map[[merkleRootPairSize]byte]*workStateBlockInfo),
		gbtWorkState:           newGbtWorkState(s.timeSource),
		helpCacher:             newHelpCacher(),
		requestProcessShutdown: make(chan struct{}),
		quit:                   make(chan int),
	}
	if cfg.RPCUser != "" && cfg.RPCPass != "" {
		login := cfg.RPCUser + ":" + cfg.RPCPass
		auth := "Basic " +
			base64.StdEncoding.EncodeToString([]byte(login))
		rpc.authsha = sha256.Sum256([]byte(auth))
	}
	if cfg.RPCLimitUser != "" && cfg.RPCLimitPass != "" {
		login := cfg.RPCLimitUser + ":" + cfg.RPCLimitPass
		auth := "Basic " +
			base64.StdEncoding.EncodeToString([]byte(login))
		rpc.limitauthsha = sha256.Sum256([]byte(auth))
	}
	rpc.ntfnMgr = newWsNotificationManager(&rpc)

	// Setup TLS if not disabled.
	listenFunc := net.Listen
	if !cfg.DisableTLS {
		// Generate the TLS cert and key file if both don't already
		// exist.
		if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
			err := genCertPair(cfg.RPCCert, cfg.RPCKey)
			if err != nil {
				return nil, err
			}
		}
		keypair, err := tls.LoadX509KeyPair(cfg.RPCCert, cfg.RPCKey)
		if err != nil {
			return nil, err
		}

		tlsConfig := tls.Config{
			Certificates: []tls.Certificate{keypair},
			MinVersion:   tls.VersionTLS12,
		}

		// Change the standard net.Listen function to the tls one.
		listenFunc = func(net string, laddr string) (net.Listener, error) {
			return tls.Listen(net, laddr, &tlsConfig)
		}
	}

	// TODO(oga) this code is similar to that in server, should be
	// factored into something shared.
	ipv4ListenAddrs, ipv6ListenAddrs, _, err := parseListeners(listenAddrs)
	if err != nil {
		return nil, err
	}
	listeners := make([]net.Listener, 0,
		len(ipv6ListenAddrs)+len(ipv4ListenAddrs))
	for _, addr := range ipv4ListenAddrs {
		listener, err := listenFunc("tcp4", addr)
		if err != nil {
			rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
			continue
		}
		listeners = append(listeners, listener)
	}

	for _, addr := range ipv6ListenAddrs {
		listener, err := listenFunc("tcp6", addr)
		if err != nil {
			rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
			continue
		}
		listeners = append(listeners, listener)
	}
	if len(listeners) == 0 {
		return nil, errors.New("RPCS: No valid listen address")
	}

	rpc.listeners = listeners

	return &rpc, nil
}

func init() {
	rpcHandlers = rpcHandlersBeforeInit
	rand.Seed(time.Now().UnixNano())

	// blake256Pad is the extra blake256 internal padding needed for the
	// data of the getwork RPC.  The internal blake256 padding consists of
	// a single 1 bit followed by zeros and a final 1 bit in order to pad
	// the message out to 56 bytes followed by length of the message in
	// bits encoded as a big-endian uint64 (8 bytes).  Thus, the resulting
	// length is a multiple of the blake256 block size (64 bytes).  Since
	// the block header is a fixed size, it only needs to be calculated
	// once.
	blake256Pad = make([]byte, getworkDataLen-wire.MaxBlockHeaderPayload)
	blake256Pad[0] = 0x80
	blake256Pad[len(blake256Pad)-9] |= 0x01
	binary.BigEndian.PutUint64(blake256Pad[len(blake256Pad)-8:],
		wire.MaxBlockHeaderPayload*8)
}
